Merged 2.061 frontend.

This commit is contained in:
David Nadlinger
2013-01-04 06:22:53 +01:00
parent 326aedd0e4
commit 5c518a16ec
91 changed files with 7638 additions and 6530 deletions
+7 -5
View File
@@ -74,7 +74,7 @@ struct AggregateDeclaration : ScopeDsymbol
bool isdeprecated; // !=0 if deprecated
#if DMDV2
int isnested; // !=0 if is nested
bool isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
#endif
// Special member functions
@@ -100,6 +100,7 @@ struct AggregateDeclaration : ScopeDsymbol
Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this)
AggregateDeclaration(Loc loc, Identifier *id);
void setScope(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
@@ -118,7 +119,7 @@ struct AggregateDeclaration : ScopeDsymbol
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
// For access checking
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
@@ -194,8 +195,9 @@ struct StructDeclaration : AggregateDeclaration
FuncDeclaration *buildCpCtor(Scope *sc);
FuncDeclaration *buildXopEquals(Scope *sc);
void makeNested();
#endif
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
PROT getAccess(Dsymbol *smember); // determine access to smember
@@ -285,7 +287,7 @@ struct ClassDeclaration : AggregateDeclaration
int isscope; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
#if DMDV1
int isnested; // !=0 if is nested
bool isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this class is nested
#endif
int inuse; // to prevent recursive attempts
@@ -319,7 +321,7 @@ struct ClassDeclaration : AggregateDeclaration
virtual int vtblOffset();
const char *kind();
char *mangle();
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
PROT getAccess(Dsymbol *smember); // determine access to smember
+23 -35
View File
@@ -34,45 +34,33 @@ int Expression::apply(fp_t fp, void *param)
}
/******************************
* Perform apply() on an array of Expressions.
* Perform apply() on an t if not null
*/
int arrayExpressionApply(Expressions *a, fp_t fp, void *param)
template<typename T>
int condApply(T* t, fp_t fp, void* param)
{
//printf("arrayExpressionApply(%p)\n", a);
if (a)
{
for (size_t i = 0; i < a->dim; i++)
{ Expression *e = (*a)[i];
if (e)
{
if (e->apply(fp, param))
return 1;
}
}
}
return 0;
return t ? t->apply(fp, param) : 0;
}
int NewExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
return condApply(thisexp, fp, param) ||
condApply(newargs, fp, param) ||
condApply(arguments, fp, param) ||
(*fp)(this, param);
}
int NewAnonClassExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewAnonClassExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
return condApply(thisexp, fp, param) ||
condApply(newargs, fp, param) ||
condApply(arguments, fp, param) ||
(*fp)(this, param);
}
int UnaExp::apply(fp_t fp, void *param)
@@ -92,7 +80,7 @@ int AssertExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
(msg ? msg->apply(fp, param) : 0) ||
condApply(msg, fp, param) ||
(*fp)(this, param);
}
@@ -101,7 +89,7 @@ int CallExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
condApply(arguments, fp, param) ||
(*fp)(this, param);
}
@@ -110,7 +98,7 @@ int ArrayExp::apply(fp_t fp, void *param)
{
//printf("ArrayExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
condApply(arguments, fp, param) ||
(*fp)(this, param);
}
@@ -118,37 +106,37 @@ int ArrayExp::apply(fp_t fp, void *param)
int SliceExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
(lwr ? lwr->apply(fp, param) : 0) ||
(upr ? upr->apply(fp, param) : 0) ||
condApply(lwr, fp, param) ||
condApply(upr, fp, param) ||
(*fp)(this, param);
}
int ArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
return condApply(elements, fp, param) ||
(*fp)(this, param);
}
int AssocArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(keys, fp, param) ||
arrayExpressionApply(values, fp, param) ||
return condApply(keys, fp, param) ||
condApply(values, fp, param) ||
(*fp)(this, param);
}
int StructLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
return condApply(elements, fp, param) ||
(*fp)(this, param);
}
int TupleExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(exps, fp, param) ||
return condApply(exps, fp, param) ||
(*fp)(this, param);
}
+2
View File
@@ -370,6 +370,8 @@ TypeTuple *TypeStruct::toArgTypes()
unsigned off2 = f->offset;
if (ft1)
off2 = 8;
if (!t2 && off2 != 8)
goto Lmemory;
assert(t2 || off2 == 8);
t2 = argtypemerge(t2, ft2, off2 - 8);
if (!t2)
+2
View File
@@ -64,6 +64,8 @@ typedef ArrayBase<struct CompoundStatement> CompoundStatements;
typedef ArrayBase<struct GotoCaseStatement> GotoCaseStatements;
typedef ArrayBase<struct ReturnStatement> ReturnStatements;
typedef ArrayBase<struct TemplateInstance> TemplateInstances;
//typedef ArrayBase<char> Strings;
+178 -20
View File
@@ -373,13 +373,13 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
buf->writenl();
buf->level++;
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = (*decl)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
buf->level--;
buf->writeByte('}');
}
}
@@ -552,6 +552,44 @@ void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
AttribDeclaration::toCBuffer(buf, hgs);
}
/********************************* DeprecatedDeclaration ****************************/
DeprecatedDeclaration::DeprecatedDeclaration(Expression *msg, Dsymbols *decl)
: StorageClassDeclaration(STCdeprecated, decl)
{
this->msg = msg;
}
Dsymbol *DeprecatedDeclaration::syntaxCopy(Dsymbol *s)
{
assert(!s);
return new DeprecatedDeclaration(msg->syntaxCopy(), Dsymbol::arraySyntaxCopy(decl));
}
void DeprecatedDeclaration::setScope(Scope *sc)
{
assert(msg);
char *depmsg = NULL;
StringExp *se = msg->toString();
if (se)
depmsg = (char *)se->string;
else
msg->error("string expected, not '%s'", msg->toChars());
Scope *scx = sc->push();
scx->depmsg = depmsg;
StorageClassDeclaration::setScope(scx);
scx->pop();
}
void DeprecatedDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("deprecated(");
msg->toCBuffer(buf, hgs);
buf->writestring(") ");
AttribDeclaration::toCBuffer(buf, hgs);
}
/********************************* LinkDeclaration ****************************/
LinkDeclaration::LinkDeclaration(enum LINK p, Dsymbols *decl)
@@ -699,17 +737,10 @@ void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection)
{
const char *p;
switch (protection)
{
case PROTprivate: p = "private"; break;
case PROTpackage: p = "package"; break;
case PROTprotected: p = "protected"; break;
case PROTpublic: p = "public"; break;
case PROTexport: p = "export"; break;
default:
assert(0);
break;
}
p = Pprotectionnames[protection];
assert(p);
buf->writestring(p);
buf->writeByte(' ');
}
@@ -887,16 +918,16 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->printf(isunion ? "union" : "struct");
buf->writestring("\n{\n");
buf->level++;
if (decl)
{
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = (*decl)[i];
//buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
}
buf->level--;
buf->writestring("}\n");
}
@@ -939,6 +970,7 @@ void PragmaDeclaration::setScope(Scope *sc)
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
StringExp* se = e->toString();
@@ -978,6 +1010,7 @@ void PragmaDeclaration::semantic(Scope *sc)
Expression *e = (*args)[i];
e = e->semantic(sc);
e = resolveProperties(sc, e);
if (e->op != TOKerror && e->op != TOKtype)
e = e->ctfeInterpret();
if (e->op == TOKerror)
@@ -1005,6 +1038,7 @@ void PragmaDeclaration::semantic(Scope *sc)
Expression *e = (*args)[0];
e = e->semantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
if (e->op == TOKerror)
@@ -1047,6 +1081,7 @@ void PragmaDeclaration::semantic(Scope *sc)
e = (*args)[1];
e = e->semantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
e = e->toString();
if (e && ((StringExp *)e)->sz == 1)
@@ -1069,6 +1104,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
Dsymbol *sa = getDsymbol(e);
@@ -1106,6 +1142,7 @@ void PragmaDeclaration::semantic(Scope *sc)
unsigned errors_save = global.errors;
e = e->semantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
if (i == 0)
printf(" (");
@@ -1349,16 +1386,16 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
buf->writenl();
buf->level++;
if (decl)
{
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = (*decl)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
}
buf->level--;
buf->writeByte('}');
if (elsedecl)
{
@@ -1367,13 +1404,13 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
buf->writenl();
buf->level++;
for (size_t i = 0; i < elsedecl->dim; i++)
{
Dsymbol *s = (*elsedecl)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
buf->level--;
buf->writeByte('}');
}
}
@@ -1420,7 +1457,7 @@ Dsymbols *StaticIfDeclaration::include(Scope *sc, ScopeDsymbol *sd)
{
Dsymbol *s = (*d)[i];
s->setScope(sc);
s->setScope(scope);
}
}
return d;
@@ -1580,3 +1617,124 @@ const char *CompileDeclaration::kind()
}
/***************************** UserAttributeDeclaration *****************************/
UserAttributeDeclaration::UserAttributeDeclaration(Expressions *atts, Dsymbols *decl)
: AttribDeclaration(decl)
{
//printf("UserAttributeDeclaration()\n");
this->atts = atts;
}
Dsymbol *UserAttributeDeclaration::syntaxCopy(Dsymbol *s)
{
//printf("UserAttributeDeclaration::syntaxCopy('%s')\n", toChars());
assert(!s);
Expressions *atts = Expression::arraySyntaxCopy(this->atts);
return new UserAttributeDeclaration(atts, Dsymbol::arraySyntaxCopy(decl));
}
void UserAttributeDeclaration::semantic(Scope *sc)
{
//printf("UserAttributeDeclaration::semantic() %p\n", this);
atts = arrayExpressionSemantic(atts, sc);
if (decl)
{
Scope *newsc = sc;
#if 1
if (atts && atts->dim)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;
// Create new uda that is the concatenation of the previous
newsc->userAttributes = concat(newsc->userAttributes, atts);
}
#endif
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];
s->semantic(newsc);
}
if (newsc != sc)
{
sc->offset = newsc->offset;
newsc->pop();
}
}
}
Expressions *UserAttributeDeclaration::concat(Expressions *udas1, Expressions *udas2)
{
Expressions *udas;
if (!udas1 || udas1->dim == 0)
udas = udas2;
else if (!udas2 || udas2->dim == 0)
udas = udas1;
else
{
/* Create a new tuple that combines them
* (do not append to left operand, as this is a copy-on-write operation)
*/
udas = new Expressions();
udas->push(new TupleExp(0, udas1));
udas->push(new TupleExp(0, udas2));
}
return udas;
}
void UserAttributeDeclaration::setScope(Scope *sc)
{
//printf("UserAttributeDeclaration::setScope() %p\n", this);
if (decl)
{
Scope *newsc = sc;
#if 1
if (atts && atts->dim)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;
// Append new atts to old one
if (!newsc->userAttributes || newsc->userAttributes->dim == 0)
newsc->userAttributes = atts;
else
{
// Create a tuple that combines them
Expressions *exps = new Expressions();
exps->push(new TupleExp(0, newsc->userAttributes));
exps->push(new TupleExp(0, atts));
newsc->userAttributes = exps;
}
}
#endif
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];
s->setScope(newsc); // yes, the only difference from semantic()
}
if (newsc != sc)
{
sc->offset = newsc->offset;
newsc->pop();
}
}
}
void UserAttributeDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("@(");
argsToCBuffer(buf, atts, hgs);
buf->writeByte(')');
AttribDeclaration::toCBuffer(buf, hgs);
}
const char *UserAttributeDeclaration::kind()
{
return "UserAttribute";
}
+28 -1
View File
@@ -67,7 +67,7 @@ struct AttribDeclaration : Dsymbol
#endif
};
struct StorageClassDeclaration: AttribDeclaration
struct StorageClassDeclaration : AttribDeclaration
{
StorageClass stc;
@@ -81,6 +81,16 @@ struct StorageClassDeclaration: AttribDeclaration
static void stcToCBuffer(OutBuffer *buf, StorageClass stc);
};
struct DeprecatedDeclaration : StorageClassDeclaration
{
Expression *msg;
DeprecatedDeclaration(Expression *msg, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct LinkDeclaration : AttribDeclaration
{
enum LINK linkage;
@@ -204,4 +214,21 @@ struct CompileDeclaration : AttribDeclaration
const char *kind();
};
/**
* User defined attributes look like:
* [ args, ... ]
*/
struct UserAttributeDeclaration : AttribDeclaration
{
Expressions *atts;
UserAttributeDeclaration(Expressions *atts, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void setScope(Scope *sc);
static Expressions *concat(Expressions *udas1, Expressions *udas2);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
};
#endif /* DMD_ATTRIB_H */
+2 -11
View File
@@ -24,16 +24,6 @@
#include "id.h"
#include "module.h"
#if __FreeBSD__
extern "C"
{
longdouble sinl(longdouble);
longdouble cosl(longdouble);
longdouble tanl(longdouble);
longdouble sqrtl(longdouble);
}
#endif
#if DMDV2
/**********************************
@@ -46,7 +36,7 @@ enum BUILTIN FuncDeclaration::isBuiltin()
static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real)
static const char FuintZint[] = "FNaNbNfkZi"; // @safe pure nothrow int function(uint)
static const char FuintZuint[] = "FNaNbNfkZk"; // @safe pure nothrow uint function(uint)
static const char FulongZulong[] = "FNaNbkZk"; // pure nothrow int function(ulong)
//static const char FulongZulong[] = "FNaNbkZk"; // pure nothrow int function(ulong)
static const char FulongZint[] = "FNaNbNfmZi"; // @safe pure nothrow int function(uint)
static const char FrealrealZreal [] = "FNaNbNfeeZe"; // @safe pure nothrow real function(real, real)
static const char FrealZlong [] = "FNaNbNfeZl"; // @safe pure nothrow long function(real)
@@ -228,6 +218,7 @@ Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments)
if (arg0->op == TOKint64)
e = new IntegerExp(loc, eval_bswap(arg0), arg0->type);
break;
default: break;
}
return e;
}
+152 -23
View File
@@ -70,7 +70,7 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
}
#endif
#if DMDV2
if (match == MATCHconst && t == type->constOf())
if (match == MATCHconst && type->constConv(t))
{
Expression *e = copy();
e->type = t;
@@ -769,7 +769,9 @@ MATCH FuncExp::implicitConvTo(Type *t)
{
//printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
Expression *e = inferType(t, 1);
if (e)
if (e &&
(t->ty == Tdelegate ||
t->ty == Tpointer && t->nextOf()->ty == Tfunction))
{
if (e != this)
return e->implicitConvTo(t);
@@ -777,13 +779,10 @@ MATCH FuncExp::implicitConvTo(Type *t)
/* MATCHconst: Conversion from implicit to explicit function pointer
* MATCHconvert: Conversion from impliict funciton pointer to delegate
*/
if (tok == TOKreserved && type->ty == Tpointer &&
(t->ty == Tpointer || t->ty == Tdelegate))
if (fd->tok == TOKreserved && // fbody doesn't have a frame pointer
(type->equals(t) || type->nextOf()->covariant(t->nextOf()) == 1))
{
if (type == t)
return MATCHexact;
if (type->nextOf()->covariant(t->nextOf()) == 1)
return t->ty == Tpointer ? MATCHconst : MATCHconvert;
return t->ty == Tpointer ? MATCHconst : MATCHconvert;
}
}
return Expression::implicitConvTo(t);
@@ -856,6 +855,122 @@ MATCH CastExp::implicitConvTo(Type *t)
return result;
}
MATCH NewExp::implicitConvTo(Type *t)
{
#if 0
printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars());
#endif
MATCH match = Expression::implicitConvTo(t);
if (match != MATCHnomatch)
return match;
/* The return from new() is special in that it might be a unique pointer.
* If we can prove it is, allow the following implicit conversions:
* mutable => immutable
* non-shared => shared
* shared => non-shared
*/
Type *typeb = type->toBasetype();
Type *tb = t->toBasetype();
if (tb->ty == Tclass)
{
//printf("%s => %s\n", type->castMod(0)->toChars(), t->castMod(0)->toChars());
match = type->castMod(0)->implicitConvTo(t->castMod(0));
if (!match)
goto Lnomatch;
// Regardless, don't allow immutable to be implicitly converted to mutable
if (tb->isMutable() && !typeb->isMutable())
goto Lnomatch;
// All the fields must be convertible as well
ClassDeclaration *cd = ((TypeClass *)tb)->sym;
cd->size(loc); // resolve any forward references
/* The following is excessively conservative, but be very
* careful in loosening them up.
*/
if (cd->isNested() ||
cd->isInterfaceDeclaration() ||
cd->ctor ||
cd->baseClass != ClassDeclaration::object)
goto Lnomatch;
for (size_t i = 0; i < cd->fields.dim; i++)
{ Dsymbol *sm = cd->fields[i];
Declaration *d = sm->isDeclaration();
if (d->storage_class & STCref || d->hasPointers())
goto Lnomatch;
}
return (match == MATCHexact) ? MATCHconst : match;
}
else if ((tb->ty == Tpointer || tb->ty == Tarray) &&
(typeb->ty == Tpointer || typeb->ty == Tarray))
{
Type *typen = type->nextOf()->toBasetype();
Type *tn = tb->nextOf()->toBasetype();
//printf("%s => %s\n", typen->castMod(0)->toChars(), tn->castMod(0)->toChars());
{
/* Determine if the match failure was solely due to a difference
* in the mod bits, by rebuilding type and t without mod bits and
* retrying the implicit conversion.
*/
Type *tn2 = tn->castMod(0); // cast off mod bits
Type *typen2 = typen->castMod(0);
Type *t2 = (tb->ty == Tpointer) ? tn2->pointerTo() : tn2->arrayOf();
Type *type2 = (typeb->ty == Tpointer) ? typen2->pointerTo() : typen2->arrayOf();
match = type2->implicitConvTo(t2);
if (!match)
goto Lnomatch;
}
// Regardless, don't allow immutable to be implicitly converted to mutable
if (tn->isMutable() && !typen->isMutable())
goto Lnomatch;
if (tn->isTypeBasic())
;
else if (tn->ty == Tstruct)
{
// All the fields must be convertible as well
StructDeclaration *sd = ((TypeStruct *)tn)->sym;
sd->size(loc); // resolve any forward references
/* The following is excessively conservative, but be very
* careful in loosening them up.
*/
if (sd->isNested() ||
sd->ctor)
goto Lnomatch;
for (size_t i = 0; i < sd->fields.dim; i++)
{ Dsymbol *sm = sd->fields[i];
Declaration *d = sm->isDeclaration();
if (d->storage_class & STCref || d->hasPointers())
goto Lnomatch;
}
}
else
{
/* More fruit left on the table, such as pointers to immutable.
*/
goto Lnomatch;
}
return (match == MATCHexact) ? MATCHconst : match;
}
Lnomatch:
return MATCHnomatch;
}
/* ==================== castTo ====================== */
/**************************************
@@ -945,6 +1060,12 @@ Expression *Expression::castTo(Scope *sc, Type *t)
e = e->semantic(sc);
return e;
}
else if (typeb->implicitConvTo(tb) == MATCHconst && t == type->constOf())
{
Expression *e = copy();
e->type = t;
return e;
}
e = new CastExp(loc, e, tb);
}
}
@@ -1132,7 +1253,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
if (committed)
goto Lcast;
#define X(tf,tt) ((tf) * 256 + (tt))
#define X(tf,tt) ((int)(tf) * 256 + (int)(tt))
{
OutBuffer buffer;
size_t newlen = 0;
@@ -1258,12 +1379,9 @@ L2:
if (dim2 != se->len)
{
// Copy when changing the string literal
unsigned newsz = se->sz;
void *s;
int d;
d = (dim2 < se->len) ? dim2 : se->len;
s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
size_t newsz = se->sz;
size_t d = (dim2 < se->len) ? dim2 : se->len;
void *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);
@@ -1634,8 +1752,15 @@ Expression *FuncExp::castTo(Scope *sc, Type *t)
//printf("FuncExp::castTo type = %s, t = %s\n", type->toChars(), t->toChars());
Expression *e = inferType(t, 1);
if (e)
{ if (e != this)
{
if (e != this)
e = e->castTo(sc, t);
else if (!e->type->equals(t))
{
assert(e->type->nextOf()->covariant(t->nextOf()) == 1);
e = e->copy();
e->type = t;
}
return e;
}
return Expression::castTo(sc, t);
@@ -1805,10 +1930,14 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
FuncLiteralDeclaration *fld = td->onemember->isFuncLiteralDeclaration();
assert(fld);
if (!fld->type->nextOf() && tfv->next)
fld->treq = tfv;
fld->treq = to;
TemplateInstance *ti = new TemplateInstance(loc, td, tiargs);
e = (new ScopeExp(loc, ti))->semantic(td->scope);
// Reset inference target for the later re-semantic
fld->treq = NULL;
if (e->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)e;
assert(fe->td == NULL);
@@ -2255,16 +2384,16 @@ Lagain:
Lcc:
while (1)
{
int i1 = e2->implicitConvTo(t1);
int i2 = e1->implicitConvTo(t2);
MATCH i1 = e2->implicitConvTo(t1);
MATCH i2 = e1->implicitConvTo(t2);
if (i1 && i2)
{
// We have the case of class vs. void*, so pick class
if (t1->ty == Tpointer)
i1 = 0;
i1 = MATCHnomatch;
else if (t2->ty == Tpointer)
i2 = 0;
i2 = MATCHnomatch;
}
if (i2)
@@ -2331,8 +2460,8 @@ Lcc:
if (!ts1->sym->aliasthis && !ts2->sym->aliasthis)
goto Lincompatible;
int i1 = 0;
int i2 = 0;
MATCH i1 = MATCHnomatch;
MATCH i2 = MATCHnomatch;
Expression *e1b = NULL;
Expression *e2b = NULL;
+39 -11
View File
@@ -27,6 +27,7 @@
#include "module.h"
#include "expression.h"
#include "statement.h"
#include "template.h"
/********************************* ClassDeclaration ****************************/
@@ -305,6 +306,7 @@ void ClassDeclaration::semantic(Scope *sc)
{
isdeprecated = true;
}
userAttributes = sc->userAttributes;
if (sc->linkage == LINKcpp)
error("cannot create C++ classes");
@@ -533,11 +535,12 @@ void ClassDeclaration::semantic(Scope *sc)
*/
if (vthis) // if inheriting from nested class
{ // Use the base class's 'this' member
isnested = 1;
isnested = true;
if (storage_class & STCstatic)
error("static class cannot inherit from nested class %s", baseClass->toChars());
if (toParent2() != baseClass->toParent2() &&
(!toParent2() ||
!baseClass->toParent2()->getType() ||
!baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
{
if (toParent2())
@@ -553,7 +556,7 @@ void ClassDeclaration::semantic(Scope *sc)
baseClass->toChars(),
baseClass->toParent2()->toChars());
}
isnested = 0;
isnested = false;
}
}
else if (!(storage_class & STCstatic))
@@ -565,7 +568,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (ad || fd)
{ isnested = 1;
{ isnested = true;
Type *t;
if (ad)
t = ad->handle;
@@ -628,6 +631,7 @@ void ClassDeclaration::semantic(Scope *sc)
{ sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor
alignsize = PTRSIZE;
}
sc->userAttributes = NULL;
structsize = sc->offset;
Scope scsave = *sc;
size_t members_dim = members->dim;
@@ -733,8 +737,9 @@ void ClassDeclaration::semantic(Scope *sc)
if (!ctor && baseClass && baseClass->ctor)
{
//printf("Creating default this(){} for class %s\n", toChars());
Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0);
Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0);
CtorDeclaration *ctor = new CtorDeclaration(loc, 0, 0, tf);
ctor->isImplicit = true;
ctor->fbody = new CompoundStatement(0, new Statements());
members->push(ctor);
ctor->addMember(sc, this, 1);
@@ -787,7 +792,30 @@ void ClassDeclaration::semantic(Scope *sc)
Module::dprogress++;
dtor = buildDtor(sc);
if (Dsymbol *assign = search_function(this, Id::assign))
{
Expression *e = new NullExp(loc, type); // dummy rvalue
Expressions *arguments = new Expressions();
arguments->push(e);
// check identity opAssign exists
FuncDeclaration *fd = assign->isFuncDeclaration();
if (fd)
{ fd = fd->overloadResolve(loc, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
goto Lassignerr;
}
if (TemplateDeclaration *td = assign->isTemplateDeclaration())
{ fd = td->deduceFunctionTemplate(sc, loc, NULL, e, arguments, 1+2);
if (fd && !(fd->storage_class & STCdisable))
goto Lassignerr;
}
Lassignerr:
if (fd && !(fd->storage_class & STCdisable))
error("identity assignment operator overload is illegal");
}
sc->pop();
#if 0 // Do not call until toObjfile() because of forward references
@@ -831,13 +859,13 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
buf->writenl();
buf->level++;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
buf->level--;
buf->writestring("}");
}
else
@@ -1280,6 +1308,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
{
isdeprecated = true;
}
userAttributes = sc->userAttributes;
// Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; )
@@ -1423,6 +1452,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
sc->explicitProtection = 0;
// structalign = sc->structalign;
sc->offset = PTRSIZE * 2;
sc->userAttributes = NULL;
structsize = sc->offset;
inuse++;
@@ -1472,11 +1502,9 @@ void InterfaceDeclaration::semantic(Scope *sc)
int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
{
unsigned j;
//printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
assert(!baseClass);
for (j = 0; j < cd->interfaces_dim; j++)
for (size_t j = 0; j < cd->interfaces_dim; j++)
{
BaseClass *b = cd->interfaces[j];
@@ -1510,7 +1538,7 @@ int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
{
//printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
for (size_t j = 0; j < bc->baseInterfaces_dim; j++)
{
BaseClass *b = &bc->baseInterfaces[j];
@@ -1680,7 +1708,7 @@ void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
//printf("%s.copyBaseInterfaces()\n", base->toChars());
for (int i = 0; i < baseInterfaces_dim; i++)
for (size_t i = 0; i < baseInterfaces_dim; i++)
{
BaseClass *b = &baseInterfaces[i];
BaseClass *b2 = base->interfaces[i];
+56 -23
View File
@@ -34,8 +34,9 @@ int StructDeclaration::needOpAssign()
{
#define X 0
if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
if (hasIdentityAssign)
goto Ldontneed;
goto Lneed; // because has identity==elaborate opAssign
if (dtor || postblit)
goto Lneed;
@@ -74,25 +75,51 @@ Lneed:
/******************************************
* Build opAssign for struct.
* S* opAssign(S s) { ... }
* ref S opAssign(S s) { ... }
*
* Note that s will be constructed onto the stack, probably copy-constructed.
* Then, the body is:
* S tmp = *this; // bit copy
* *this = s; // bit copy
* S tmp = this; // bit copy
* this = s; // bit copy
* tmp.dtor();
* Instead of running the destructor on s, run it on tmp instead.
*/
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
{
Dsymbol *assign = search_function(this, Id::assign);
if (assign)
{
/* check identity opAssign exists
*/
Expression *er = new NullExp(loc, type); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
el->type = type;
Expressions ar; ar.push(er);
Expressions al; al.push(el);
if (FuncDeclaration *fd = assign->isFuncDeclaration())
{
FuncDeclaration *f = fd->overloadResolve(loc, er, &ar, 1);
if (f == NULL) f = fd->overloadResolve(loc, er, &al, 1);
if (f)
return (f->storage_class & STCdisable) ? NULL : f;
}
if (TemplateDeclaration *td = assign->isTemplateDeclaration())
{
FuncDeclaration *f = td->deduceFunctionTemplate(sc, loc, NULL, er, &ar, 1);
if (f == NULL) f = td->deduceFunctionTemplate(sc, loc, NULL, er, &al, 1);
if (f)
return (f->storage_class & STCdisable) ? NULL : f;
}
// Even if non-identity opAssign is defined, built-in identity opAssign
// will be defined. (Is this an exception of operator overloading rule?)
}
if (!needOpAssign())
return NULL;
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
FuncDeclaration *fop = NULL;
Parameters *fparams = new Parameters;
fparams->push(new Parameter(STCnodtor, type, Id::p, NULL));
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
@@ -100,7 +127,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
((TypeFunction *)ftype)->isref = 1;
#endif
fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype);
FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype);
Expression *e = NULL;
if (postblit)
@@ -160,7 +187,6 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
AssignExp *ec = new AssignExp(0,
new DotVarExp(0, new ThisExp(0), v, 0),
new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
ec->op = TOKblit;
e = Expression::combine(e, ec);
}
}
@@ -174,15 +200,24 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
fop->fbody = new CompoundStatement(0, s1, s2);
members->push(fop);
fop->addMember(sc, this, 1);
Dsymbol *s = fop;
if (assign && assign->isTemplateDeclaration())
{
// Wrap a template around the function declaration
TemplateParameters *tpl = new TemplateParameters();
Dsymbols *decldefs = new Dsymbols();
decldefs->push(s);
TemplateDeclaration *tempdecl =
new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0);
s = tempdecl;
}
members->push(s);
s->addMember(sc, this, 1);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fop->semantic(sc);
s->semantic(sc);
sc->pop();
//printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
@@ -357,10 +392,10 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::p, NULL));
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::q, NULL));
TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tf = (TypeFunction *)tf->semantic(loc, sc);
tf = (TypeFunction *)tf->semantic(0, sc);
Identifier *id = Lexer::idPool("__xopEquals");
FuncDeclaration *fop = new FuncDeclaration(loc, 0, id, STCstatic, tf);
FuncDeclaration *fop = new FuncDeclaration(0, 0, id, STCstatic, tf);
Expression *e = new CallExp(0,
new DotIdExp(0,
@@ -370,7 +405,7 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
new PtrExp(0, new CastExp(0,
new IdentifierExp(0, Id::q), type->pointerTo()->constOf())));
fop->fbody = new ReturnStatement(loc, e);
fop->fbody = new ReturnStatement(0, e);
size_t index = members->dim;
members->push(fop);
@@ -395,9 +430,9 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
if (!xerreq)
{
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, Lexer::idPool("_xopEquals"));
Expression *e = new IdentifierExp(0, Id::empty);
e = new DotIdExp(0, e, Id::object);
e = new DotIdExp(0, e, Lexer::idPool("_xopEquals"));
e = e->semantic(sc);
Dsymbol *s = getDsymbol(e);
FuncDeclaration *fd = s->isFuncDeclaration();
@@ -567,8 +602,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
*/
if (e || (stc & STCdisable))
{ //printf("Building __fieldPostBlit()\n");
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__fieldPostBlit"));
dd->storage_class |= stc;
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, stc, Lexer::idPool("__fieldPostBlit"));
dd->fbody = new ExpStatement(0, e);
postblits.shift(dd);
members->push(dd);
@@ -598,8 +632,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
ex = new CallExp(0, ex);
e = Expression::combine(e, ex);
}
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__aggrPostBlit"));
dd->storage_class |= stc;
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, stc, Lexer::idPool("__aggrPostBlit"));
dd->fbody = new ExpStatement(0, e);
members->push(dd);
dd->semantic(sc);
+1
View File
@@ -266,6 +266,7 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
sc->sd = s; // s gets any addMember()
sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc);
e = resolveProperties(sc, e);
sc->pop();
if (!e->type->checkBoolean())
{
+13 -5
View File
@@ -910,6 +910,14 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
break;
}
}
#if !IN_LLVM
// LDC_FIXME: Implement this.
if (cmp && es1->type->needsNested())
{
if ((es1->sinit != NULL) != (es2->sinit != NULL))
cmp = 0;
}
#endif
}
#if 0 // Should handle this
else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
@@ -1495,7 +1503,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
/* Set a slice of char array literal 'existingAE' from a string 'newval'.
* existingAE[firstIndex..firstIndex+newval.length] = newval.
*/
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex)
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex)
{
size_t newlen = newval->len;
size_t sz = newval->sz;
@@ -1521,7 +1529,7 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *n
/* Set a slice of string 'existingSE' from a char array literal 'newae'.
* existingSE[firstIndex..firstIndex+newae.length] = newae.
*/
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex)
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex)
{
unsigned char *s = (unsigned char *)existingSE->string;
for (size_t j = 0; j < newae->elements->dim; j++)
@@ -1542,7 +1550,7 @@ void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *n
/* Set a slice of string 'existingSE' from a string 'newstr'.
* existingSE[firstIndex..firstIndex+newstr.length] = newstr.
*/
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex)
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex)
{
unsigned char *s = (unsigned char *)existingSE->string;
size_t sz = existingSE->sz;
@@ -1621,7 +1629,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
StringExp *es;
if (t->nextOf())
t = t->nextOf()->toBasetype();
int sz = t->size();
size_t sz = t->size();
dinteger_t v = e->toInteger();
@@ -1740,7 +1748,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
void *s;
StringExp *es1 = (StringExp *)e1;
StringExp *es;
int sz = es1->sz;
size_t sz = es1->sz;
dinteger_t v = e2->toInteger();
// Is it a concatentation of homogenous types?
+41 -29
View File
@@ -133,8 +133,7 @@ void cpp_mangle_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
{
s->error("C++ static variables not supported");
}
else
if (fd->isConst())
else if (fd->type->isConst())
buf->writeByte('K');
prefix_name(buf, cms, p);
@@ -411,38 +410,51 @@ void TypeClass::toCppMangle(OutBuffer *buf, CppMangleState *cms)
}
}
struct ArgsCppMangleCtx
{
OutBuffer *buf;
CppMangleState *cms;
size_t cnt;
};
static int argsCppMangleDg(void *ctx, size_t n, Parameter *arg)
{
ArgsCppMangleCtx *p = (ArgsCppMangleCtx *)ctx;
Type *t = arg->type;
if (arg->storageClass & (STCout | STCref))
t = t->referenceTo();
else if (arg->storageClass & STClazy)
{ // Mangle as delegate
Type *td = new TypeFunction(NULL, t, 0, LINKd);
td = new TypeDelegate(td);
t = t->merge();
}
if (t->ty == Tsarray)
{ // Mangle static arrays as pointers
t = t->pointerTo();
}
/* If it is a basic, enum or struct type,
* then don't mark it const
*/
if ((t->ty == Tenum || t->ty == Tstruct || t->isTypeBasic()) && t->isConst())
t->mutableOf()->toCppMangle(p->buf, p->cms);
else
t->toCppMangle(p->buf, p->cms);
p->cnt++;
return 0;
}
void Parameter::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs)
{ int n = 0;
{
size_t n = 0;
if (arguments)
{
for (size_t i = 0; i < arguments->dim; i++)
{ Parameter *arg = (*arguments)[i];
Type *t = arg->type;
if (arg->storageClass & (STCout | STCref))
t = t->referenceTo();
else if (arg->storageClass & STClazy)
{ // Mangle as delegate
Type *td = new TypeFunction(NULL, t, 0, LINKd);
td = new TypeDelegate(td);
t = t->merge();
}
if (t->ty == Tsarray)
{ // Mangle static arrays as pointers
t = t->pointerTo();
}
/* If it is a basic, enum or struct type,
* then don't mark it const
*/
if ((t->ty == Tenum || t->ty == Tstruct || t->isTypeBasic()) && t->isConst())
t->mutableOf()->toCppMangle(buf, cms);
else
t->toCppMangle(buf, cms);
n++;
}
ArgsCppMangleCtx ctx = { buf, cms, 0 };
foreach(arguments, &argsCppMangleDg, &ctx);
n = ctx.cnt;
}
if (varargs)
buf->writestring("z");
+243
View File
@@ -0,0 +1,243 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_CTFE_H
#define DMD_CTFE_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
/**
Global status of the CTFE engine. Mostly used for performance diagnostics
*/
struct CtfeStatus
{
static int callDepth; // current number of recursive calls
static int stackTraceCallsToSuppress; /* When printing a stack trace,
* suppress this number of calls
*/
static int maxCallDepth; // highest number of recursive calls
static int numArrayAllocs; // Number of allocated arrays
static int numAssignments; // total number of assignments executed
};
/** Expression subclasses which only exist in CTFE */
#define TOKclassreference ((TOK)(TOKMAX+1))
#define TOKthrownexception ((TOK)(TOKMAX+2))
/**
A reference to a class, or an interface. We need this when we
point to a base class (we must record what the type is).
*/
struct ClassReferenceExp : Expression
{
StructLiteralExp *value;
ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
char *toChars();
ClassDeclaration *originalClass();
VarDeclaration *getFieldAt(unsigned index);
/// Return index of the field, or -1 if not found
int getFieldIndex(Type *fieldtype, unsigned fieldoffset);
/// Return index of the field, or -1 if not found
/// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(VarDeclaration *v);
};
/// Return index of the field, or -1 if not found
/// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v);
/** An uninitialized value
*/
struct VoidInitExp : Expression
{
VarDeclaration *var;
VoidInitExp(VarDeclaration *var, Type *type);
char *toChars();
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
};
/** Fake class which holds the thrown exception.
Used for implementing exception handling.
*/
struct ThrownExceptionExp : Expression
{
ClassReferenceExp *thrown; // the thing being tossed
ThrownExceptionExp(Loc loc, ClassReferenceExp *victim);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
char *toChars();
/// Generate an error message when this exception is not caught
void generateUncaughtError();
};
/// True if 'e' is EXP_CANT_INTERPRET, or an exception
bool exceptionOrCantInterpret(Expression *e);
// Used for debugging only
void showCtfeExpr(Expression *e, int level = 0);
/// Return true if this is a valid CTFE expression
bool isCtfeValueValid(Expression *newval);
/// Given expr, which evaluates to an array/AA/string literal,
/// return true if it needs to be copied
bool needToCopyLiteral(Expression *expr);
/// Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral.
/// This value will be used for in-place modification.
Expression *copyLiteral(Expression *e);
/// Set this literal to the given type, copying it if necessary
Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
/// Convert from a CTFE-internal slice, into a normal Expression
Expression *resolveSlice(Expression *e);
/// Determine the array length, without interpreting the expression.
uinteger_t resolveArrayLength(Expression *e);
/// Create an array literal consisting of 'elem' duplicated 'dim' times.
ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
Expression *elem, size_t dim);
/// Create a string literal consisting of 'value' duplicated 'dim' times.
StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
unsigned value, size_t dim, int sz);
/* Set dest = src, where both dest and src are container value literals
* (ie, struct literals, or static arrays (can be an array literal or a string)
* Assignment is recursively in-place.
* Purpose: any reference to a member of 'dest' will remain valid after the
* assignment.
*/
void assignInPlace(Expression *dest, Expression *src);
/// Set all elements of 'ae' to 'val'. ae may be a multidimensional array.
/// If 'wantRef', all elements of ae will hold references to the same val.
void recursiveBlockAssign(ArrayLiteralExp *ae, Expression *val, bool wantRef);
/// Duplicate the elements array, then set field 'indexToChange' = newelem.
Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem);
/// Create a new struct literal, which is the same as se except that se.field[offset] = elem
Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, Expression *newval);
/// Given an AA literal aae, set arr[index] = newval and return the new array.
Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae,
Expression *index, Expression *newval);
/// Given array literal oldval of type ArrayLiteralExp or StringExp, of length
/// oldlen, change its length to newlen. If the newlen is longer than oldlen,
/// all new elements will be set to the default initializer for the element type.
Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
Expression *oldval, size_t oldlen, size_t newlen);
/// Return true if t is a pointer (not a function pointer)
bool isPointer(Type *t);
// For CTFE only. Returns true if 'e' is TRUE or a non-null pointer.
int isTrueBool(Expression *e);
/// Is it safe to convert from srcPointee* to destPointee* ?
/// srcPointee is the genuine type (never void).
/// destPointee may be void.
bool isSafePointerCast(Type *srcPointee, Type *destPointee);
/// Given pointer e, return the memory block expression it points to,
/// and set ofs to the offset within that memory block.
Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs);
/// Return true if agg1 and agg2 are pointers to the same memory block
bool pointToSameMemoryBlock(Expression *agg1, Expression *agg2);
// return e1 - e2 as an integer, or error if not possible
Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2);
/// Return 1 if true, 0 if false
/// -1 if comparison is illegal because they point to non-comparable memory blocks
int comparePointers(Loc loc, enum TOK op, Type *type, Expression *agg1, dinteger_t ofs1, Expression *agg2, dinteger_t ofs2);
// Return eptr op e2, where eptr is a pointer, e2 is an integer,
// and op is TOKadd or TOKmin
Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
Expression *eptr, Expression *e2);
// True if conversion from type 'from' to 'to' involves a reinterpret_cast
// floating point -> integer or integer -> floating point
bool isFloatIntPaint(Type *to, Type *from);
// Reinterpret float/int value 'fromVal' as a float/integer of type 'to'.
Expression *paintFloatInt(Expression *fromVal, Type *to);
/// Return true if t is an AA, or AssociativeArray!(key, value)
bool isAssocArray(Type *t);
/// Given a template AA type, extract the corresponding built-in AA type
TypeAArray *toBuiltinAAType(Type *t);
/* Given an AA literal 'ae', and a key 'e2':
* Return ae[e2] if present, or NULL if not found.
* Return EXP_CANT_INTERPRET on error.
*/
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2);
/***********************************************
In-place integer operations
***********************************************/
/// e = OP e
void intUnary(TOK op, IntegerExp *e);
/// dest = e1 OP e2;
void intBinary(TOK op, IntegerExp *dest, Type *type, IntegerExp *e1, IntegerExp *e2);
/***********************************************
COW const-folding operations
***********************************************/
/// Return true if non-pointer expression e can be compared
/// with >,is, ==, etc, using ctfeCmp, ctfeEquals, ctfeIdentity
bool isCtfeComparable(Expression *e);
/// Evaluate ==, !=. Resolves slices before comparing. Returns 0 or 1
int ctfeEqual(Loc loc, enum TOK op, Expression *e1, Expression *e2);
/// Evaluate is, !is. Resolves slices before comparing. Returns 0 or 1
int ctfeIdentity(Loc loc, enum TOK op, Expression *e1, Expression *e2);
/// Evaluate >,<=, etc. Resolves slices before comparing. Returns 0 or 1
int ctfeCmp(Loc loc, enum TOK op, Expression *e1, Expression *e2);
/// Returns e1 ~ e2. Resolves slices before concatenation.
Expression *ctfeCat(Type *type, Expression *e1, Expression *e2);
/// Same as for constfold.Index, except that it only works for static arrays,
/// dynamic arrays, and strings.
Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx);
/// Cast 'e' of type 'type' to type 'to'.
Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e);
#endif /* DMD_CTFE_H */
+2091
View File
File diff suppressed because it is too large Load Diff
+149 -64
View File
@@ -24,6 +24,51 @@
#include "statement.h"
#include "hdrgen.h"
AggregateDeclaration *isAggregate(Type *t); // from opover.c
void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad)
{
if (!ad->isnested)
return;
Dsymbol *s = sc->func;
if (s)
{
Dsymbol *sparent = ad->toParent2();
//printf("ad = %p %s [%s], parent:%p\n", ad, ad->toChars(), ad->loc.toChars(), ad->parent);
//printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent->toChars(), sparent->loc.toChars(), sparent->parent->toChars());
while (s)
{
if (s == sparent) // hit!
{
// Is it better moving this check to AggregateDeclaration:semantic?
for (size_t i = 0; i < ad->fields.dim; i++)
{ VarDeclaration *vd = ad->fields[i]->isVarDeclaration();
if (vd)
if (AggregateDeclaration *ad2 = isAggregate(vd->type))
if (ad2->isStructDeclaration())
checkFrameAccess(loc, sc, ad2);
}
return;
}
if (FuncDeclaration *fd = s->isFuncDeclaration())
{
if (!fd->isThis() && !fd->isNested())
break;
}
if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
{
if (ad2->storage_class & STCstatic)
break;
}
s = s->toParent2();
}
}
error(loc, "cannot access frame pointer of %s", ad->toPrettyChars());
}
/********************************* Declaration ****************************/
Declaration::Declaration(Identifier *id)
@@ -85,40 +130,26 @@ enum PROT Declaration::prot()
#if DMDV2
void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
int Declaration::checkModify(Loc loc, Scope *sc, Type *t)
{
if (sc->incontract && isParameter())
if ((sc->flags & SCOPEcontract) && isParameter())
error(loc, "cannot modify parameter '%s' in contract", toChars());
if (sc->incontract && isResult())
if ((sc->flags & SCOPEcontract) && isResult())
error(loc, "cannot modify result '%s' in contract", toChars());
if (isCtorinit() && !t->isMutable() ||
(storage_class & STCnodefaultctor))
{ // It's only modifiable if inside the right constructor
modifyFieldVar(loc, sc, isVarDeclaration(), NULL);
return modifyFieldVar(loc, sc, isVarDeclaration(), NULL);
}
else
{
VarDeclaration *v = isVarDeclaration();
if (v && v->canassign == 0)
{
const char *p = NULL;
if (isConst())
p = "const";
else if (isImmutable())
p = "immutable";
else if (isWild())
p = "inout";
else if (storage_class & STCmanifest)
p = "enum";
else if (!t->isAssignable())
p = "struct with immutable members";
if (p)
{ error(loc, "cannot modify %s", p);
}
}
if (v && v->canassign)
return TRUE;
}
return FALSE;
}
#endif
@@ -304,6 +335,7 @@ Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
void TypedefDeclaration::semantic(Scope *sc)
{
//printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
userAttributes = sc->userAttributes;
if (sem == SemanticStart)
{ sem = SemanticIn;
parent = sc->parent;
@@ -332,6 +364,7 @@ void TypedefDeclaration::semantic(Scope *sc)
return;
}
storage_class |= sc->stc & STCdeprecated;
userAttributes = sc->userAttributes;
}
else if (sem == SemanticIn)
{
@@ -430,6 +463,7 @@ Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
else
sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
sa->storage_class = storage_class;
// Syntax copy for header file
if (!htype) // Don't overwrite original
@@ -470,6 +504,7 @@ void AliasDeclaration::semantic(Scope *sc)
storage_class |= sc->stc & STCdeprecated;
protection = sc->protection;
userAttributes = sc->userAttributes;
// Given:
// alias foo.bar.abc def;
@@ -534,7 +569,7 @@ void AliasDeclaration::semantic(Scope *sc)
//printf("\talias resolved to type %s\n", type->toChars());
}
if (overnext)
ScopeDsymbol::multiplyDefined(0, this, overnext);
ScopeDsymbol::multiplyDefined(0, overnext, this);
this->inSemantic = 0;
if (global.gag && errors != global.errors)
@@ -563,7 +598,7 @@ void AliasDeclaration::semantic(Scope *sc)
fa->importprot = importprot;
#endif
if (!fa->overloadInsert(overnext))
ScopeDsymbol::multiplyDefined(0, f, overnext);
ScopeDsymbol::multiplyDefined(0, overnext, f);
overnext = NULL;
s = fa;
s->parent = sc->parent;
@@ -581,7 +616,7 @@ void AliasDeclaration::semantic(Scope *sc)
}
}
if (overnext)
ScopeDsymbol::multiplyDefined(0, this, overnext);
ScopeDsymbol::multiplyDefined(0, overnext, this);
if (s == this)
{
assert(global.errors);
@@ -731,7 +766,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
aliassym = NULL;
onstack = 0;
canassign = 0;
ctfeAdrOnStack = (size_t)(-1);
ctfeAdrOnStack = -1;
#if DMDV2
rundtor = NULL;
edtor = NULL;
@@ -813,6 +848,8 @@ void VarDeclaration::semantic(Scope *sc)
if (storage_class & STCextern && init)
error("extern symbols cannot have initializers");
userAttributes = sc->userAttributes;
AggregateDeclaration *ad = isThis();
if (ad)
storage_class |= ad->storage_class & STC_TYPECTOR;
@@ -858,11 +895,11 @@ void VarDeclaration::semantic(Scope *sc)
* declarations.
*/
storage_class &= ~STCauto;
originalType = type;
originalType = type->syntaxCopy();
}
else
{ if (!originalType)
originalType = type;
originalType = type->syntaxCopy();
type = type->semantic(loc, sc);
}
//printf(" semantic type = %s\n", type ? type->toChars() : "null");
@@ -1262,7 +1299,27 @@ Lnomatch:
{
// Provide a default initializer
//printf("Providing default initializer for '%s'\n", toChars());
if (type->ty == Tstruct &&
if (type->needsNested())
{
Type *tv = type;
while (tv->toBasetype()->ty == Tsarray)
tv = tv->toBasetype()->nextOf();
assert(tv->toBasetype()->ty == Tstruct);
/* Nested struct requires valid enclosing frame pointer.
* In StructLiteralExp::toElem(), it's calculated.
*/
checkFrameAccess(loc, sc, ((TypeStruct *)tv->toBasetype())->sym);
Expression *e = tv->defaultInitLiteral(loc);
Expression *e1 = new VarExp(loc, this);
e = new ConstructExp(loc, e1, e);
e = e->semantic(sc);
init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type->ty == Tstruct &&
((TypeStruct *)type)->sym->zeroInit == 1)
{ /* If a struct is all zeros, as a special case
* set it's initializer to the integer 0.
@@ -1278,19 +1335,6 @@ Lnomatch:
init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type->ty == Tstruct &&
(((TypeStruct *)type)->sym->isnested))
{
/* Nested struct requires valid enclosing frame pointer.
* In StructLiteralExp::toElem(), it's calculated.
*/
Expression *e = type->defaultInitLiteral(loc);
Expression *e1 = new VarExp(loc, this);
e = new ConstructExp(loc, e1, e);
e = e->semantic(sc);
init = new ExpInitializer(loc, e);
goto Ldtor;
}
else if (type->ty == Ttypedef)
{ TypeTypedef *td = (TypeTypedef *)type;
if (td->sym->init)
@@ -1501,7 +1545,7 @@ Lnomatch:
ei->exp = new CommaExp(loc, e, ei->exp);
}
else
/* Look for opCall
/* Look for static opCall
* See bugzilla 2702 for more discussion
*/
// Don't cast away invariant or mutability in initializer
@@ -1510,8 +1554,8 @@ Lnomatch:
*/
!(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc)))
{ // Rewrite as e1.call(arguments)
Expression * eCall = new DotIdExp(loc, e1, Id::call);
ei->exp = new CallExp(loc, eCall, ei->exp);
Expression *e = typeDotIdExp(ei->exp->loc, t, Id::call);
ei->exp = new CallExp(loc, e, ei->exp);
}
}
}
@@ -1528,8 +1572,7 @@ Lnomatch:
}
}
else if (storage_class & (STCconst | STCimmutable | STCmanifest) ||
type->isConst() || type->isImmutable() ||
parent->isAggregateDeclaration())
type->isConst() || type->isImmutable())
{
/* Because we may need the results of a const declaration in a
* subsequent type, such as an array dimension, before semantic2()
@@ -1540,15 +1583,18 @@ Lnomatch:
if (!global.errors && !inferred)
{
unsigned errors = global.startGagging();
Expression *e;
Expression *exp;
Initializer *i2 = init;
inuse++;
if (ei)
{
e = ei->exp->syntaxCopy();
e = e->semantic(sc);
e = resolveProperties(sc, e);
exp = ei->exp->syntaxCopy();
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
#if DMDV2
Type *tb = type->toBasetype();
Type *ti = exp->type->toBasetype();
/* The problem is the following code:
* struct CopyTest {
* double x;
@@ -1560,21 +1606,18 @@ Lnomatch:
* static assert(w.x == 55.0);
* because the postblit doesn't get run on the initialization of w.
*/
Type *tb2 = e->type->toBasetype();
if (tb2->ty == Tstruct)
{ StructDeclaration *sd = ((TypeStruct *)tb2)->sym;
Type *typeb = type->toBasetype();
if (ti->ty == Tstruct)
{ StructDeclaration *sd = ((TypeStruct *)ti)->sym;
/* Look to see if initializer involves a copy constructor
* (which implies a postblit)
*/
if (sd->cpctor && // there is a copy constructor
typeb->equals(tb2)) // rvalue is the same struct
tb->equals(ti)) // rvalue is the same struct
{
// The only allowable initializer is a (non-copy) constructor
if (e->op == TOKcall)
if (exp->op == TOKcall)
{
CallExp *ce = (CallExp *)e;
CallExp *ce = (CallExp *)exp;
if (ce->e1->op == TOKdotvar)
{
DotVarExp *dve = (DotVarExp *)ce->e1;
@@ -1583,15 +1626,33 @@ Lnomatch:
}
}
global.gag--;
error("of type struct %s uses this(this), which is not allowed in static initialization", typeb->toChars());
error("of type struct %s uses this(this), which is not allowed in static initialization", tb->toChars());
global.gag++;
LNoCopyConstruction:
;
}
}
// Look for implicit constructor call
if (tb->ty == Tstruct &&
!(ti->ty == Tstruct && tb->toDsymbol(sc) == ti->toDsymbol(sc)) &&
!exp->implicitConvTo(type))
{
StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->ctor)
{ // Look for constructor first
// Rewrite as e1.ctor(arguments)
Expression *e;
e = new StructLiteralExp(loc, sd, NULL, NULL);
e = new DotIdExp(loc, e, Id::ctor);
e = new CallExp(loc, e, exp);
e = e->semantic(sc);
exp = e->ctfeInterpret();
}
}
#endif
e = e->implicitCastTo(sc, type);
exp = exp->implicitCastTo(sc, type);
}
else if (si || ai)
{ i2 = init->syntaxCopy();
@@ -1610,10 +1671,10 @@ Lnomatch:
else if (ei)
{
if (isDataseg() || (storage_class & STCmanifest))
e = e->ctfeInterpret();
exp = exp->ctfeInterpret();
else
e = e->optimize(WANTvalue);
switch (e->op)
exp = exp->optimize(WANTvalue);
switch (exp->op)
{
case TOKint64:
case TOKfloat64:
@@ -1622,7 +1683,7 @@ Lnomatch:
case TOKassocarrayliteral:
case TOKstructliteral:
case TOKnull:
ei->exp = e; // no errors, keep result
ei->exp = exp; // no errors, keep result
break;
default:
@@ -1639,6 +1700,11 @@ Lnomatch:
init = i2; // no errors, keep result
}
}
else if (parent->isAggregateDeclaration())
{
scope = new Scope(*sc);
scope->setNoFree();
}
sc = sc->pop();
}
@@ -1765,6 +1831,25 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}
#if DMDV2
else if (t->ty == Tsarray)
{
Type *tv = t->toBasetype();
while (tv->ty == Tsarray)
{
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{
TypeStruct *ts = (TypeStruct *)tv;
if (ad == ts->sym)
{
ad->error("cannot have field %s with same struct type", toChars());
return;
}
}
}
#endif
unsigned memsize = t->size(loc); // size of member
unsigned memalignsize = t->alignsize(); // size of member for alignment purposes
+22 -15
View File
@@ -152,13 +152,13 @@ struct Declaration : Dsymbol
void semantic(Scope *sc);
const char *kind();
unsigned size(Loc loc);
void checkModify(Loc loc, Scope *sc, Type *t);
int checkModify(Loc loc, Scope *sc, Type *t);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
char *mangle();
int isStatic() { return storage_class & STCstatic; }
@@ -236,7 +236,7 @@ struct TypedefDeclaration : Declaration
Type *htype;
Type *hbasetype;
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
@@ -278,7 +278,7 @@ struct AliasDeclaration : Declaration
Type *htype;
Dsymbol *haliassym;
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
AliasDeclaration *isAliasDeclaration() { return this; }
};
@@ -289,7 +289,7 @@ struct VarDeclaration : Declaration
{
Initializer *init;
unsigned offset;
int noscope; // no auto semantics
bool noscope; // no auto semantics
#if DMDV2
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
bool isargptr; // if parameter that _argptr points to
@@ -297,15 +297,15 @@ struct VarDeclaration : Declaration
int nestedref; // referenced by a lexically nested function
#endif
structalign_t alignment;
int ctorinit; // it has been initialized in a ctor
int onstack; // 1: it has been allocated on the stack
bool ctorinit; // it has been initialized in a ctor
short onstack; // 1: it has been allocated on the stack
// 2: on stack, run destructor anyway
int canassign; // it can be assigned to
Dsymbol *aliassym; // if redone as alias to another symbol
// When interpreting, these point to the value (NULL if value not determinable)
// The index of this variable on the CTFE stack, -1 if not allocated
size_t ctfeAdrOnStack;
int ctfeAdrOnStack;
// The various functions are used only to detect compiler CTFE bugs
Expression *getValue();
bool hasValue();
@@ -766,16 +766,20 @@ struct FuncDeclaration : Declaration
Declaration *overnext; // next in overload list
Loc endloc; // location of closing curly bracket
int vtblIndex; // for member functions, index into vtbl[]
int naked; // !=0 if naked
bool naked; // !=0 if naked
ILS inlineStatusStmt;
ILS inlineStatusExp;
int inlineNest; // !=0 if nested inline
int isArrayOp; // !=0 if array operation
#if IN_LLVM
char isArrayOp; // 1 if compiler-generated array op, 2 if druntime-provided
#else
bool isArrayOp; // !=0 if array operation
#endif
enum PASS semanticRun;
int semantic3Errors; // !=0 if errors in semantic3
// this function's frame ptr
ForeachStatement *fes; // if foreach body, this is the foreach
int introducing; // !=0 if 'introducing' function
bool introducing; // !=0 if 'introducing' function
Type *tintro; // if !=NULL, then this is the type
// of the 'introducing' function
// this one is overriding
@@ -789,12 +793,14 @@ struct FuncDeclaration : Declaration
// 8 if there's inline asm
// Support for NRVO (named return value optimization)
int nrvo_can; // !=0 means we can do it
bool nrvo_can; // !=0 means we can do it
VarDeclaration *nrvo_var; // variable to replace with shidden
#if IN_DMD
Symbol *shidden; // hidden pointer passed to function
#endif
ReturnStatements *returns;
#if DMDV2
enum BUILTIN builtin; // set if this is a known, builtin
// function we can evaluate at compile
@@ -802,6 +808,7 @@ struct FuncDeclaration : Declaration
int tookAddressOf; // set if someone took the address of
// this function
bool requiresClosure; // this function needs a closure
VarDeclarations closureVars; // local variables in this function
// which are referenced by nested
// functions
@@ -870,7 +877,7 @@ struct FuncDeclaration : Declaration
int canInline(int hasthis, int hdrscan = false, int statementsToo = true);
Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps);
const char *kind();
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
FuncDeclaration *isUnique();
void checkNestedReference(Scope *sc, Loc loc);
int needsClosure();
@@ -990,6 +997,7 @@ struct CtorDeclaration : FuncDeclaration
int isVirtual();
int addPreInvariant();
int addPostInvariant();
bool isImplicit; // implicitly generated ctor
CtorDeclaration *isCtorDeclaration() { return this; }
};
@@ -997,8 +1005,7 @@ struct CtorDeclaration : FuncDeclaration
#if DMDV2
struct PostBlitDeclaration : FuncDeclaration
{
PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc = STCundefined);
PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-2150
View File
File diff suppressed because it is too large Load Diff
+220 -110
View File
@@ -19,7 +19,7 @@
#include "rmem.h"
#include "root.h"
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include "gnuc.h"
#endif
@@ -49,10 +49,10 @@ struct Escape
struct Section
{
unsigned char *name;
unsigned namelen;
size_t namelen;
unsigned char *body;
unsigned bodylen;
size_t bodylen;
int nooutput;
@@ -86,8 +86,8 @@ struct DocComment
{ }
static DocComment *parse(Scope *sc, Dsymbol *s, unsigned char *comment);
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen);
static void parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen);
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, size_t mlen);
static void parseEscapes(Escape **pescapetable, unsigned char *textstart, size_t textlen);
void parseSections(unsigned char *comment);
void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf);
@@ -98,13 +98,13 @@ int cmp(const char *stringz, void *s, size_t slen);
int icmp(const char *stringz, void *s, size_t slen);
int isDitto(unsigned char *comment);
unsigned char *skipwhitespace(unsigned char *p);
unsigned skiptoident(OutBuffer *buf, size_t i);
unsigned skippastident(OutBuffer *buf, size_t i);
unsigned skippastURL(OutBuffer *buf, size_t i);
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len);
size_t skiptoident(OutBuffer *buf, size_t i);
size_t skippastident(OutBuffer *buf, size_t i);
size_t skippastURL(OutBuffer *buf, size_t i);
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool anchor = true);
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, size_t len);
int isIdStart(unsigned char *p);
int isIdTail(unsigned char *p);
@@ -191,6 +191,7 @@ DDOC_PARAM_ID = $(TD $0)\n\
DDOC_PARAM_DESC = $(TD $0)\n\
DDOC_BLANKLINE = $(BR)$(BR)\n\
\n\
DDOC_ANCHOR = <a name=\"$1\"></a>\n\
DDOC_PSYMBOL = $(U $0)\n\
DDOC_KEYWORD = $(B $0)\n\
DDOC_PARAM = $(I $0)\n\
@@ -233,7 +234,7 @@ void Module::gendocfile()
// Override with the ddoc macro files from the command line
for (size_t i = 0; i < global.params.ddocfiles->dim; i++)
{
FileName f((*global.params.ddocfiles)[i], 0);
FileName f((*global.params.ddocfiles)[i]);
File file(&f);
file.readv();
// BUG: convert file contents to UTF-8 before use
@@ -302,7 +303,7 @@ void Module::gendocfile()
OutBuffer buf2;
buf2.writestring("$(DDOC)\n");
unsigned end = buf2.offset;
size_t end = buf2.offset;
macrotable->expand(&buf2, 0, &end, NULL, 0);
#if 1
@@ -313,7 +314,7 @@ void Module::gendocfile()
buf.setsize(0);
buf.reserve(buf2.offset);
unsigned char *p = buf2.data;
for (unsigned j = 0; j < buf2.offset; j++)
for (size_t j = 0; j < buf2.offset; j++)
{
unsigned char c = p[j];
if (c == 0xFF && j + 1 < buf2.offset)
@@ -348,9 +349,9 @@ void Module::gendocfile()
#else
/* Remove all the escape sequences from buf2
*/
{ unsigned i = 0;
{ size_t i = 0;
unsigned char *p = buf2.data;
for (unsigned j = 0; j < buf2.offset; j++)
for (size_t j = 0; j < buf2.offset; j++)
{
if (p[j] == 0xFF && j + 1 < buf2.offset)
{
@@ -381,9 +382,9 @@ void Module::gendocfile()
* to preserve text literally. This also means macros in the
* text won't be expanded.
*/
void escapeDdocString(OutBuffer *buf, unsigned start)
void escapeDdocString(OutBuffer *buf, size_t start)
{
for (unsigned u = start; u < buf->offset; u++)
for (size_t u = start; u < buf->offset; u++)
{
unsigned char c = buf->data[u];
switch(c)
@@ -415,11 +416,11 @@ void escapeDdocString(OutBuffer *buf, unsigned start)
* Fix by replacing unmatched ( with $(LPAREN) and unmatched ) with $(RPAREN).
*/
void escapeStrayParenthesis(OutBuffer *buf, unsigned start, Loc loc)
void escapeStrayParenthesis(OutBuffer *buf, size_t start, Loc loc)
{
unsigned par_open = 0;
for (unsigned u = start; u < buf->offset; u++)
for (size_t u = start; u < buf->offset; u++)
{
unsigned char c = buf->data[u];
switch(c)
@@ -432,8 +433,7 @@ void escapeStrayParenthesis(OutBuffer *buf, unsigned start, Loc loc)
if (par_open == 0)
{
//stray ')'
if (global.params.warnings)
warning(loc, "Ddoc: Stray ')'. This may cause incorrect Ddoc output."
warning(loc, "Ddoc: Stray ')'. This may cause incorrect Ddoc output."
" Use $(RPAREN) instead for unpaired right parentheses.");
buf->remove(u, 1); //remove the )
buf->insert(u, "$(RPAREN)", 9); //insert this instead
@@ -455,7 +455,7 @@ void escapeStrayParenthesis(OutBuffer *buf, unsigned start, Loc loc)
if (par_open) // if any unmatched lparens
{ par_open = 0;
for (unsigned u = buf->offset; u > start;)
for (size_t u = buf->offset; u > start;)
{ u--;
unsigned char c = buf->data[u];
switch(c)
@@ -468,8 +468,7 @@ void escapeStrayParenthesis(OutBuffer *buf, unsigned start, Loc loc)
if (par_open == 0)
{
//stray '('
if (global.params.warnings)
warning(loc, "Ddoc: Stray '('. This may cause incorrect Ddoc output."
warning(loc, "Ddoc: Stray '('. This may cause incorrect Ddoc output."
" Use $(LPAREN) instead for unpaired left parentheses.");
buf->remove(u, 1); //remove the (
buf->insert(u, "$(LPAREN)", 9); //insert this instead
@@ -492,12 +491,12 @@ void Dsymbol::emitDitto(Scope *sc)
{
//printf("Dsymbol::emitDitto() %s %s\n", kind(), toChars());
OutBuffer *buf = sc->docbuf;
unsigned o;
size_t o;
OutBuffer b;
b.writestring("$(DDOC_DITTO ");
o = b.offset;
toDocBuffer(&b);
toDocBuffer(&b, sc);
//printf("b: '%.*s'\n", b.offset, b.data);
/* If 'this' is a function template, then highlightCode() was
* already run by FuncDeclaration::toDocbuffer().
@@ -559,15 +558,8 @@ void ScopeDsymbol::emitMemberComments(Scope *sc)
void emitProtection(OutBuffer *buf, PROT prot)
{
const char *p;
const char *p = (prot == PROTpublic) ? NULL : Pprotectionnames[prot];
switch (prot)
{
case PROTpackage: p = "package"; break;
case PROTprotected: p = "protected"; break;
case PROTexport: p = "export"; break;
default: p = NULL; break;
}
if (p)
buf->printf("%s ", p);
}
@@ -598,7 +590,7 @@ void Declaration::emitComment(Scope *sc)
OutBuffer *buf = sc->docbuf;
DocComment *dc = DocComment::parse(sc, this, comment);
unsigned o;
size_t o;
if (!dc)
{
@@ -609,7 +601,7 @@ void Declaration::emitComment(Scope *sc)
buf->writestring(ddoc_decl_s);
o = buf->offset;
toDocBuffer(buf);
toDocBuffer(buf, sc);
highlightCode(sc, this, buf, o);
sc->lastoffset = buf->offset;
buf->writestring(ddoc_decl_e);
@@ -638,7 +630,7 @@ void AggregateDeclaration::emitComment(Scope *sc)
dc->pmacrotable = &sc->module->macrotable;
buf->writestring(ddoc_decl_s);
toDocBuffer(buf);
toDocBuffer(buf, sc);
sc->lastoffset = buf->offset;
buf->writestring(ddoc_decl_e);
@@ -680,7 +672,7 @@ void TemplateDeclaration::emitComment(Scope *sc)
OutBuffer *buf = sc->docbuf;
DocComment *dc = DocComment::parse(sc, this, com);
unsigned o;
size_t o;
if (!dc)
{
@@ -691,7 +683,7 @@ void TemplateDeclaration::emitComment(Scope *sc)
buf->writestring(ddoc_decl_s);
o = buf->offset;
ss->toDocBuffer(buf);
ss->toDocBuffer(buf, sc);
if (ss == this)
highlightCode(sc, this, buf, o);
sc->lastoffset = buf->offset;
@@ -735,7 +727,7 @@ void EnumDeclaration::emitComment(Scope *sc)
dc->pmacrotable = &sc->module->macrotable;
buf->writestring(ddoc_decl_s);
toDocBuffer(buf);
toDocBuffer(buf, sc);
sc->lastoffset = buf->offset;
buf->writestring(ddoc_decl_e);
@@ -755,7 +747,7 @@ void EnumMember::emitComment(Scope *sc)
OutBuffer *buf = sc->docbuf;
DocComment *dc = DocComment::parse(sc, this, comment);
unsigned o;
size_t o;
if (!dc)
{
@@ -766,7 +758,7 @@ void EnumMember::emitComment(Scope *sc)
buf->writestring(ddoc_decl_s);
o = buf->offset;
toDocBuffer(buf);
toDocBuffer(buf, sc);
highlightCode(sc, this, buf, o);
sc->lastoffset = buf->offset;
buf->writestring(ddoc_decl_e);
@@ -776,9 +768,45 @@ void EnumMember::emitComment(Scope *sc)
buf->writestring(ddoc_decl_dd_e);
}
static bool emitAnchorName(OutBuffer *buf, Dsymbol *s)
{
if (!s || s->isPackage() || s->isModule())
return false;
TemplateDeclaration *td;
bool dot;
// Add parent names first
dot = emitAnchorName(buf, s->parent);
// Eponymous template members can share the parent anchor name
if (s->parent && (td = s->parent->isTemplateDeclaration()) != NULL &&
td->onemember == s)
return dot;
if (dot)
buf->writeByte('.');
// Use "this" not "__ctor"
if (s->isCtorDeclaration() || ((td = s->isTemplateDeclaration()) != NULL &&
td->onemember && td->onemember->isCtorDeclaration()))
buf->writestring("this");
else
{
/* We just want the identifier, not overloads like TemplateDeclaration::toChars.
* We don't want the template parameter list and constraints. */
buf->writestring(s->Dsymbol::toChars());
}
return true;
}
static void emitAnchor(OutBuffer *buf, Dsymbol *s)
{
buf->writestring("$(DDOC_ANCHOR ");
emitAnchorName(buf, s);
buf->writeByte(')');
}
/******************************* toDocBuffer **********************************/
void Dsymbol::toDocBuffer(OutBuffer *buf)
void Dsymbol::toDocBuffer(OutBuffer *buf, Scope *sc)
{
//printf("Dsymbol::toDocbuffer() %s\n", toChars());
HdrGenState hgs;
@@ -795,18 +823,20 @@ void prefix(OutBuffer *buf, Dsymbol *s)
if (d)
{
emitProtection(buf, d->protection);
if (d->isAbstract())
buf->writestring("abstract ");
if (d->isStatic())
buf->writestring("static ");
else if (d->isFinal())
buf->writestring("final ");
else if (d->isAbstract())
buf->writestring("abstract ");
if (d->isConst())
buf->writestring("const ");
#if DMDV2
if (d->isImmutable())
buf->writestring("immutable ");
#endif
if (d->isFinal())
buf->writestring("final ");
if (d->isSynchronized())
buf->writestring("synchronized ");
}
@@ -837,12 +867,12 @@ void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclarati
}
}
void Declaration::toDocBuffer(OutBuffer *buf)
void Declaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
declarationToDocBuffer(this, buf, NULL);
}
void AliasDeclaration::toDocBuffer(OutBuffer *buf)
void AliasDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
//printf("AliasDeclaration::toDocbuffer() %s\n", toChars());
if (ident)
@@ -852,13 +882,83 @@ void AliasDeclaration::toDocBuffer(OutBuffer *buf)
emitProtection(buf, protection);
buf->writestring("alias ");
if (Dsymbol *s = aliassym) // ident alias
{
prettyPrintDsymbol(buf, s, parent);
}
else if (Type *type = getType()) // type alias
{
if (type->ty == Tclass || type->ty == Tstruct || type->ty == Tenum)
{
if (Dsymbol *s = type->toDsymbol(NULL)) // elaborate type
prettyPrintDsymbol(buf, s, parent);
else
buf->writestring(type->toChars());
}
else
{
// simple type
buf->writestring(type->toChars());
}
}
buf->writestring(" ");
buf->writestring(toChars());
buf->writestring(";\n");
}
}
void parentToBuffer(OutBuffer *buf, Dsymbol *s)
{
if (s && !s->isPackage() && !s->isModule())
{
parentToBuffer(buf, s->parent);
buf->writestring(s->toChars());
buf->writestring(".");
}
}
void TypedefDeclaration::toDocBuffer(OutBuffer *buf)
bool inSameModule(Dsymbol *s, Dsymbol *p)
{
for ( ; s ; s = s->parent)
{
if (s->isModule())
break;
}
for ( ; p ; p = p->parent)
{
if (p->isModule())
break;
}
return s == p;
}
void prettyPrintDsymbol(OutBuffer *buf, Dsymbol *s, Dsymbol *parent)
{
if (s->parent && (s->parent == parent)) // in current scope -> naked name
{
buf->writestring(s->toChars());
}
else
if (!inSameModule(s, parent)) // in another module -> full name
{
buf->writestring(s->toPrettyChars());
}
else // nested in a type in this module -> full name w/o module name
{
// if alias is nested in a user-type use module-scope lookup
if (!parent->isModule() && !parent->isPackage())
buf->writestring(".");
parentToBuffer(buf, s->parent);
buf->writestring(s->toChars());
}
}
void TypedefDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
if (ident)
{
@@ -873,7 +973,7 @@ void TypedefDeclaration::toDocBuffer(OutBuffer *buf)
}
void FuncDeclaration::toDocBuffer(OutBuffer *buf)
void FuncDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
//printf("FuncDeclaration::toDocbuffer() %s\n", toChars());
if (ident)
@@ -885,7 +985,7 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
td->onemember == this)
{ /* It's a function template
*/
unsigned o = buf->offset;
size_t o = buf->offset;
declarationToDocBuffer(this, buf, td);
@@ -893,13 +993,13 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
}
else
{
Declaration::toDocBuffer(buf);
Declaration::toDocBuffer(buf, sc);
}
}
}
#if DMDV1
void CtorDeclaration::toDocBuffer(OutBuffer *buf)
void CtorDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
HdrGenState hgs;
@@ -909,10 +1009,11 @@ void CtorDeclaration::toDocBuffer(OutBuffer *buf)
}
#endif
void AggregateDeclaration::toDocBuffer(OutBuffer *buf)
void AggregateDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
if (ident)
{
emitAnchor(buf, this);
#if 0
emitProtection(buf, protection);
#endif
@@ -921,7 +1022,7 @@ void AggregateDeclaration::toDocBuffer(OutBuffer *buf)
}
}
void StructDeclaration::toDocBuffer(OutBuffer *buf)
void StructDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
//printf("StructDeclaration::toDocbuffer() %s\n", toChars());
if (ident)
@@ -934,19 +1035,20 @@ void StructDeclaration::toDocBuffer(OutBuffer *buf)
if (parent &&
(td = parent->isTemplateDeclaration()) != NULL &&
td->onemember == this)
{ unsigned o = buf->offset;
td->toDocBuffer(buf);
{ size_t o = buf->offset;
td->toDocBuffer(buf, sc);
highlightCode(NULL, this, buf, o);
}
else
{
emitAnchor(buf, this);
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
}
buf->writestring(";\n");
}
}
void ClassDeclaration::toDocBuffer(OutBuffer *buf)
void ClassDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
//printf("ClassDeclaration::toDocbuffer() %s\n", toChars());
if (ident)
@@ -959,12 +1061,13 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf)
if (parent &&
(td = parent->isTemplateDeclaration()) != NULL &&
td->onemember == this)
{ unsigned o = buf->offset;
td->toDocBuffer(buf);
{ size_t o = buf->offset;
td->toDocBuffer(buf, sc);
highlightCode(NULL, this, buf, o);
}
else
{
emitAnchor(buf, this);
if (isAbstract())
buf->writestring("abstract ");
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
@@ -1000,16 +1103,17 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf)
}
void EnumDeclaration::toDocBuffer(OutBuffer *buf)
void EnumDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
if (ident)
{
emitAnchor(buf, this);
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
buf->writestring(";\n");
}
}
void EnumMember::toDocBuffer(OutBuffer *buf)
void EnumMember::toDocBuffer(OutBuffer *buf, Scope *sc)
{
if (ident)
{
@@ -1062,10 +1166,10 @@ void DocComment::parseSections(unsigned char *comment)
unsigned char *pstart;
unsigned char *pend;
unsigned char *idstart;
unsigned idlen;
size_t idlen;
unsigned char *name = NULL;
unsigned namelen = 0;
size_t namelen = 0;
//printf("parseSections('%s')\n", comment);
p = comment;
@@ -1188,7 +1292,7 @@ void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
else
{
buf->writestring("$(DDOC_SUMMARY ");
unsigned o = buf->offset;
size_t o = buf->offset;
buf->write(sec->body, sec->bodylen);
escapeStrayParenthesis(buf, o, s->loc);
highlightText(sc, s, buf, o);
@@ -1216,7 +1320,7 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
"RETURNS", "SEE_ALSO", "STANDARDS", "THROWS",
"VERSION" };
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
for (size_t i = 0; i < sizeof(table) / sizeof(table[0]); i++)
{
if (icmp(table[i], name, namelen) == 0)
{
@@ -1228,8 +1332,8 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
buf->writestring("$(DDOC_SECTION ");
// Replace _ characters with spaces
buf->writestring("$(DDOC_SECTION_H ");
unsigned o = buf->offset;
for (unsigned u = 0; u < namelen; u++)
size_t o = buf->offset;
for (size_t u = 0; u < namelen; u++)
{ unsigned char c = name[u];
buf->writeByte((c == '_') ? ' ' : c);
}
@@ -1241,7 +1345,7 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
buf->writestring("$(DDOC_DESCRIPTION ");
}
L1:
unsigned o = buf->offset;
size_t o = buf->offset;
buf->write(body, bodylen);
escapeStrayParenthesis(buf, o, s->loc);
highlightText(sc, s, buf, o);
@@ -1254,19 +1358,19 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
{
unsigned char *p = body;
unsigned len = bodylen;
size_t len = bodylen;
unsigned char *pend = p + len;
unsigned char *tempstart;
unsigned templen;
size_t templen;
unsigned char *namestart;
unsigned namelen = 0; // !=0 if line continuation
size_t namelen = 0; // !=0 if line continuation
unsigned char *textstart;
unsigned textlen;
size_t textlen;
unsigned o;
size_t o;
Parameter *arg;
buf->writestring("$(DDOC_PARAMS \n");
@@ -1326,7 +1430,7 @@ void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
else
buf->write(namestart, namelen);
escapeStrayParenthesis(buf, o, s->loc);
highlightCode(sc, s, buf, o);
highlightCode(sc, s, buf, o, false);
buf->writestring(")\n");
buf->writestring("$(DDOC_PARAM_DESC ");
@@ -1384,20 +1488,20 @@ void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
* name2 = value2
*/
void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen)
void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, size_t mlen)
{
unsigned char *p = m;
unsigned len = mlen;
size_t len = mlen;
unsigned char *pend = p + len;
unsigned char *tempstart;
unsigned templen;
size_t templen;
unsigned char *namestart;
unsigned namelen = 0; // !=0 if line continuation
size_t namelen = 0; // !=0 if line continuation
unsigned char *textstart;
unsigned textlen;
size_t textlen;
while (p < pend)
{
@@ -1509,7 +1613,7 @@ Ldone:
* by whitespace and/or commas.
*/
void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, unsigned textlen)
void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, size_t textlen)
{ Escape *escapetable = *pescapetable;
if (!escapetable)
@@ -1618,7 +1722,7 @@ unsigned char *skipwhitespace(unsigned char *p)
* end of buf
*/
unsigned skiptoident(OutBuffer *buf, size_t i)
size_t skiptoident(OutBuffer *buf, size_t i)
{
while (i < buf->offset)
{ dchar_t c;
@@ -1645,7 +1749,7 @@ unsigned skiptoident(OutBuffer *buf, size_t i)
* Scan forward past end of identifier.
*/
unsigned skippastident(OutBuffer *buf, size_t i)
size_t skippastident(OutBuffer *buf, size_t i)
{
while (i < buf->offset)
{ dchar_t c;
@@ -1677,10 +1781,10 @@ unsigned skippastident(OutBuffer *buf, size_t i)
* index just past it if it is a URL
*/
unsigned skippastURL(OutBuffer *buf, size_t i)
{ unsigned length = buf->offset - i;
size_t skippastURL(OutBuffer *buf, size_t i)
{ size_t length = buf->offset - i;
unsigned char *p = &buf->data[i];
unsigned j;
size_t j;
unsigned sawdot = 0;
if (length > 7 && memicmp((char *)p, "http://", 7) == 0)
@@ -1721,7 +1825,7 @@ Lno:
/****************************************************
*/
int isKeyword(unsigned char *p, unsigned len)
int isKeyword(unsigned char *p, size_t len)
{
static const char *table[] = { "true", "false", "null" };
@@ -1736,7 +1840,7 @@ int isKeyword(unsigned char *p, unsigned len)
/****************************************************
*/
Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len)
Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, size_t len)
{
FuncDeclaration *f = s->isFuncDeclaration();
@@ -1771,7 +1875,7 @@ Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len)
* Highlight text section.
*/
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
{
//printf("highlightText()\n");
const char *sid = s->ident->toChars();
@@ -1782,11 +1886,11 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
int leadingBlank = 1;
int inCode = 0;
//int inComment = 0; // in <!-- ... --> comment
unsigned iCodeStart; // start of code section
size_t iCodeStart; // start of code section
unsigned iLineStart = offset;
size_t iLineStart = offset;
for (unsigned i = offset; i < buf->offset; i++)
for (size_t i = offset; i < buf->offset; i++)
{ unsigned char c = buf->data[i];
Lcont:
@@ -1815,7 +1919,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
// Skip over comments
if (p[1] == '!' && p[2] == '-' && p[3] == '-')
{ unsigned j = i + 4;
{ size_t j = i + 4;
p += 4;
while (1)
{
@@ -1834,7 +1938,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
// Skip over HTML tag
if (isalpha(p[1]) || (p[1] == '/' && isalpha(p[2])))
{ unsigned j = i + 2;
{ size_t j = i + 2;
p += 2;
while (1)
{
@@ -1898,8 +2002,8 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
* inCode tells us if it is start or end of a code section.
*/
if (leadingBlank)
{ int istart = i;
int eollen = 0;
{ size_t istart = i;
size_t eollen = 0;
leadingBlank = 0;
while (1)
@@ -1953,7 +2057,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
buf->remove(iCodeStart, i - iCodeStart);
i = buf->insert(iCodeStart, codebuf.data, codebuf.offset);
i = buf->insert(i, ")\n", 2);
i--;
i -= 2; // in next loop, c should be '\n'
}
else
{ static char pre[] = "$(D_CODE \n";
@@ -1970,12 +2074,11 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
default:
leadingBlank = 0;
if (sc && !inCode && isIdStart(&buf->data[i]))
{ unsigned j;
j = skippastident(buf, i);
{
size_t j = skippastident(buf, i);
if (j > i)
{
unsigned k = skippastURL(buf, i);
size_t k = skippastURL(buf, i);
if (k > i)
{ i = k - 1;
break;
@@ -2023,13 +2126,21 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
* Highlight code for DDOC section.
*/
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool anchor)
{
if (anchor)
{
OutBuffer ancbuf;
emitAnchor(&ancbuf, s);
buf->insert(offset, (char *)ancbuf.data, ancbuf.offset);
offset += ancbuf.offset;
}
char *sid = s->ident->toChars();
FuncDeclaration *f = s->isFuncDeclaration();
//printf("highlightCode(s = '%s', kind = %s)\n", sid, s->kind());
for (unsigned i = offset; i < buf->offset; i++)
for (size_t i = offset; i < buf->offset; i++)
{ unsigned char c = buf->data[i];
const char *se;
@@ -2042,9 +2153,8 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
i--; // point to ';'
}
else if (isIdStart(&buf->data[i]))
{ unsigned j;
j = skippastident(buf, i);
{
size_t j = skippastident(buf, i);
if (j > i)
{
if (cmp(sid, buf->data + i, j - i) == 0)
@@ -2086,7 +2196,7 @@ void highlightCode3(OutBuffer *buf, unsigned char *p, unsigned char *pend)
*/
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
{
char *sid = s->ident->toChars();
FuncDeclaration *f = s->isFuncDeclaration();
+4 -1
View File
@@ -15,6 +15,9 @@
#pragma once
#endif /* __DMC__ */
void escapeDdocString(OutBuffer *buf, unsigned start);
void escapeDdocString(OutBuffer *buf, size_t start);
void parentToBuffer(OutBuffer *buf, Dsymbol *s);
bool inSameModule(Dsymbol *s, Dsymbol *p);
void prettyPrintDsymbol(OutBuffer *buf, Dsymbol *s, Dsymbol *parent);
#endif
+155 -86
View File
@@ -31,6 +31,8 @@
#include "import.h"
#include "template.h"
#include "attrib.h"
#include "enum.h"
#if IN_LLVM
#include "../gen/pragma.h"
#endif
@@ -51,6 +53,7 @@ Dsymbol::Dsymbol()
this->comment = NULL;
this->scope = NULL;
this->errors = false;
this->userAttributes = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
@@ -71,6 +74,8 @@ Dsymbol::Dsymbol(Identifier *ident)
this->comment = NULL;
this->scope = NULL;
this->errors = false;
this->depmsg = NULL;
this->userAttributes = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
@@ -230,10 +235,8 @@ const char *Dsymbol::toPrettyChars()
return s;
}
char *Dsymbol::locToChars()
Loc& Dsymbol::getLoc()
{
OutBuffer buf;
if (!loc.filename) // avoid bug 5861.
{
Module *m = getModule();
@@ -241,7 +244,12 @@ char *Dsymbol::locToChars()
if (m && m->srcfile)
loc.filename = m->srcfile->toChars();
}
return loc.toChars();
return loc;
}
char *Dsymbol::locToChars()
{
return getLoc().toChars();
}
const char *Dsymbol::kind()
@@ -331,6 +339,8 @@ void Dsymbol::setScope(Scope *sc)
if (!sc->nofree)
sc->setNoFree(); // may need it even after semantic() finishes
scope = sc;
if (sc->depmsg)
depmsg = sc->depmsg;
}
void Dsymbol::importAll(Scope *sc)
@@ -494,7 +504,7 @@ void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
unsigned Dsymbol::size(Loc loc)
{
error("Dsymbol '%s' has no size\n", toChars());
error("Dsymbol '%s' has no size", toChars());
return 0;
}
@@ -516,6 +526,14 @@ AggregateDeclaration *Dsymbol::isAggregateMember() // are we a member of an
return NULL;
}
AggregateDeclaration *Dsymbol::isAggregateMember2() // are we a member of an aggregate?
{
Dsymbol *parent = toParent2();
if (parent && parent->isAggregateDeclaration())
return (AggregateDeclaration *)parent;
return NULL;
}
ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class?
{
AggregateDeclaration *ad = isAggregateMember();
@@ -612,17 +630,9 @@ int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
void Dsymbol::error(const char *format, ...)
{
//printf("Dsymbol::error()\n");
if (!loc.filename) // avoid bug 5861.
{
Module *m = getModule();
if (m && m->srcfile)
loc.filename = m->srcfile->toChars();
}
va_list ap;
va_start(ap, format);
verror(loc, format, ap, kind(), toPrettyChars());
::verror(getLoc(), format, ap, kind(), toPrettyChars());
va_end(ap);
}
@@ -630,13 +640,29 @@ void Dsymbol::error(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap, kind(), toPrettyChars());
::verror(loc, format, ap, kind(), toPrettyChars());
va_end(ap);
}
void Dsymbol::deprecation(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
::vdeprecation(loc, format, ap, kind(), toPrettyChars());
va_end(ap);
}
void Dsymbol::deprecation(const char *format, ...)
{
va_list ap;
va_start(ap, format);
::vdeprecation(getLoc(), format, ap, kind(), toPrettyChars());
va_end(ap);
}
void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
{
if (!global.params.useDeprecated && isDeprecated())
if (global.params.useDeprecated != 1 && isDeprecated())
{
// Don't complain if we're inside a deprecated symbol's scope
for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
@@ -654,7 +680,18 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
goto L1;
}
error(loc, "is deprecated");
char *message = NULL;
for (Dsymbol *p = this; p; p = p->parent)
{
message = p->depmsg;
if (message)
break;
}
if (message)
deprecation(loc, "is deprecated - %s", message);
else
deprecation(loc, "is deprecated");
}
L1:
@@ -769,7 +806,7 @@ void Dsymbol::addComment(unsigned char *comment)
if (!this->comment)
this->comment = comment;
#if 1
else if (comment && strcmp((char *)comment, (char *)this->comment))
else if (comment && strcmp((char *)comment, (char *)this->comment) != 0)
{ // Concatenate the two
this->comment = Lexer::combineComments(this->comment, comment);
}
@@ -939,11 +976,27 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
if (s)
{
Declaration *d = s->isDeclaration();
if (d && d->protection == PROTprivate &&
!d->parent->isTemplateMixin() &&
!(flags & 2))
error(loc, "%s is private", d->toPrettyChars());
if (!(flags & 2))
{ Declaration *d = s->isDeclaration();
if (d && d->protection == PROTprivate &&
!d->parent->isTemplateMixin())
error(loc, "%s is private", d->toPrettyChars());
AggregateDeclaration *ad = s->isAggregateDeclaration();
if (ad && ad->protection == PROTprivate &&
!ad->parent->isTemplateMixin())
error(loc, "%s is private", ad->toPrettyChars());
EnumDeclaration *ed = s->isEnumDeclaration();
if (ed && ed->protection == PROTprivate &&
!ed->parent->isTemplateMixin())
error(loc, "%s is private", ed->toPrettyChars());
TemplateDeclaration *td = s->isTemplateDeclaration();
if (td && td->protection == PROTprivate &&
!td->parent->isTemplateMixin())
error(loc, "%s is private", td->toPrettyChars());
}
}
}
return s;
@@ -1006,7 +1059,7 @@ void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
}
else
{
s1->error(loc, "conflicts with %s %s at %s",
s1->error(s1->loc, "conflicts with %s %s at %s",
s2->kind(),
s2->toPrettyChars(),
s2->locToChars());
@@ -1242,13 +1295,10 @@ ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s)
Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
{
//printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
if (ident == Id::length || ident == Id::dollar)
if (ident == Id::dollar)
{ VarDeclaration **pvar;
Expression *ce;
if (ident == Id::length && !global.params.useDeprecated)
error("using 'length' inside [ ] is deprecated, use '$' instead");
L1:
if (td)
@@ -1294,62 +1344,9 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
* $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
*/
ArrayExp *ae = (ArrayExp *)exp;
AggregateDeclaration *ad = NULL;
Type *t = ae->e1->type->toBasetype();
if (t->ty == Tclass)
{
ad = ((TypeClass *)t)->sym;
}
else if (t->ty == Tstruct)
{
ad = ((TypeStruct *)t)->sym;
}
assert(ad);
Dsymbol *dsym = search_function(ad, Id::opDollar);
if (!dsym) // no dollar exists -- search in higher scope
return NULL;
VarDeclaration *v = ae->lengthVar;
if (!v)
{ // $ is lazily initialized. Create it now.
TemplateDeclaration *td = dsym->isTemplateDeclaration();
if (td)
{ // Instantiate opDollar!(dim) with the index as a template argument
Objects *tdargs = new Objects();
tdargs->setDim(1);
Expression *x = new IntegerExp(0, ae->currentDimension, Type::tsize_t);
x = x->semantic(sc);
tdargs->data[0] = x;
//TemplateInstance *ti = new TemplateInstance(loc, td, tdargs);
//ti->semantic(sc);
DotTemplateInstanceExp *dte = new DotTemplateInstanceExp(loc, ae->e1, td->ident, tdargs);
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, dte));
}
else
{ /* opDollar exists, but it's a function, not a template.
* This is acceptable ONLY for single-dimension indexing.
* Note that it's impossible to have both template & function opDollar,
* because both take no arguments.
*/
if (ae->arguments->dim != 1) {
ae->error("%s only defines opDollar for one dimension", ad->toChars());
return NULL;
}
FuncDeclaration *fd = dsym->isFuncDeclaration();
assert(fd);
Expression * x = new DotVarExp(loc, ae->e1, fd);
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, x));
}
v->semantic(sc);
ae->lengthVar = v;
}
return v;
pvar = &ae->lengthVar;
ce = ae->e1;
}
else
/* Didn't find $, look in enclosing scope(s).
@@ -1375,15 +1372,87 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
if (!*pvar) // if not already initialized
{ /* Create variable v and set it to the value of $
*/
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
VarDeclaration *v;
Type *t;
if (ce->op == TOKtuple)
{ /* It is for an expression tuple, so the
* length will be a const.
*/
Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(0, e));
v->storage_class |= STCstatic | STCconst;
}
else if (ce->type && (t = ce->type->toBasetype()) != NULL &&
(t->ty == Tstruct || t->ty == Tclass))
{ // Look for opDollar
assert(exp->op == TOKarray || exp->op == TOKslice);
AggregateDeclaration *ad = NULL;
if (t->ty == Tclass)
{
ad = ((TypeClass *)t)->sym;
}
else if (t->ty == Tstruct)
{
ad = ((TypeStruct *)t)->sym;
}
assert(ad);
Dsymbol *s = ad->search(loc, Id::opDollar, 0);
if (!s) // no dollar exists -- search in higher scope
return NULL;
s = s->toAlias();
Expression *e = NULL;
// Check for multi-dimensional opDollar(dim) template.
if (TemplateDeclaration *td = s->isTemplateDeclaration())
{
dinteger_t dim;
if (exp->op == TOKarray)
{
dim = ((ArrayExp *)exp)->currentDimension;
e = ((ArrayExp *)exp)->e1;
}
else if (exp->op == TOKslice)
{
dim = 0; // slices are currently always one-dimensional
e = ((SliceExp *)exp)->e1;
}
assert(e);
Objects *tdargs = new Objects();
Expression *edim = new IntegerExp(0, dim, Type::tsize_t);
edim = edim->semantic(sc);
tdargs->push(edim);
//TemplateInstance *ti = new TemplateInstance(loc, td, tdargs);
//ti->semantic(sc);
e = new DotTemplateInstanceExp(loc, e, td->ident, tdargs);
}
else
{ /* opDollar exists, but it's not a template.
* This is acceptable ONLY for single-dimension indexing.
* Note that it's impossible to have both template & function opDollar,
* because both take no arguments.
*/
if (exp->op == TOKarray && ((ArrayExp *)exp)->arguments->dim != 1)
{
exp->error("%s only defines opDollar for one dimension", ad->toChars());
return NULL;
}
Declaration *d = s->isDeclaration();
assert(d);
e = new DotVarExp(loc, ce, d);
}
e = e->semantic(sc);
if (!e->type)
exp->error("%s has no value", e->toChars());
t = e->type->toBasetype();
if (t && t->ty == Tfunction)
e = new CallExp(e->loc, e);
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, e));
}
else
{ /* For arrays, $ will either be a compile-time constant
* (in which case its value in set during constant-folding),
@@ -1392,7 +1461,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
*/
VoidInitializer *e = new VoidInitializer(0);
e->type = Type::tsize_t;
v->init = e;
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e);
v->storage_class |= STCctfe; // it's never a true static variable
}
*pvar = v;
+12 -3
View File
@@ -120,6 +120,9 @@ enum PROT
PROTexport,
};
// this is used for printing the protection in json, traits, docs, etc.
static const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};
/* State of symbol in winding its way through the passes of the compiler
*/
enum PASS
@@ -148,15 +151,20 @@ struct Dsymbol : Object
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
bool errors; // this symbol failed to pass semantic()
char *depmsg; // customized deprecation message
Expressions *userAttributes; // user defined attributes from UserAttributeDeclaration
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
Loc& getLoc();
char *locToChars();
int equals(Object *o);
int isAnonymous();
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void error(const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...);
void error(const char *format, ...);
void deprecation(Loc loc, const char *format, ...);
void deprecation(const char *format, ...);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule(); // module where declared
Module *getAccessModule();
@@ -189,13 +197,14 @@ struct Dsymbol : Object
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual void toDocBuffer(OutBuffer *buf, Scope *sc);
virtual void toJsonBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
AggregateDeclaration *isAggregateMember(); // are we a member of an aggregate?
AggregateDeclaration *isAggregateMember2(); // are we a member of an aggregate?
ClassDeclaration *isClassMember(); // are we a member of a class?
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
+3 -4
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -2372,15 +2372,14 @@ static NameId* namesTable[] = {
namesS, namesT, namesU, namesV, namesW, namesX, namesY, namesZ, NULL
};
int HtmlNamedEntity(unsigned char *p, int length)
int HtmlNamedEntity(unsigned char *p, size_t length)
{
int tableIndex = tolower(*p) - 'a';
if (tableIndex >= 0 && tableIndex < 26)
{
NameId* names = namesTable[tableIndex];
int i;
for (i = 0; names[i].name; i++)
for (size_t i = 0; names[i].name; i++)
{
if (strncmp(names[i].name, (char *)p, length) == 0)
return names[i].value;
+4 -1
View File
@@ -115,8 +115,10 @@ void EnumDeclaration::semantic(Scope *sc)
if (sc->stc & STCdeprecated)
isdeprecated = 1;
userAttributes = sc->userAttributes;
parent = sc->parent;
protection = sc->protection;
/* The separate, and distinct, cases are:
* 1. enum { ... }
@@ -347,16 +349,17 @@ void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
buf->writenl();
buf->level++;
for (size_t i = 0; i < members->dim; i++)
{
EnumMember *em = (*members)[i]->isEnumMember();
if (!em)
continue;
//buf->writestring(" ");
em->toCBuffer(buf, hgs);
buf->writeByte(',');
buf->writenl();
}
buf->level--;
buf->writeByte('}');
buf->writenl();
}
+3 -2
View File
@@ -29,6 +29,7 @@ struct EnumDeclaration : ScopeDsymbol
*/
Type *type; // the TypeEnum
Type *memtype; // type of the members
enum PROT protection;
#if DMDV1
dinteger_t maxval;
@@ -61,7 +62,7 @@ struct EnumDeclaration : ScopeDsymbol
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
EnumDeclaration *isEnumDeclaration() { return this; }
@@ -92,7 +93,7 @@ struct EnumMember : Dsymbol
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf, Scope *sc);
EnumMember *isEnumMember() { return this; }
};
+792 -392
View File
File diff suppressed because it is too large Load Diff
+70 -52
View File
@@ -91,16 +91,21 @@ void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *h
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void expandTuples(Expressions *exps);
TupleDeclaration *isAliasThisTuple(Expression *e);
int expandAliasThisTuples(Expressions *exps, int starti = 0);
int expandAliasThisTuples(Expressions *exps, size_t starti = 0);
FuncDeclaration *hasThis(Scope *sc);
Expression *fromConstInitializer(int result, Expression *e);
int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s);
void valueNoDtor(Expression *e);
void modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
#if DMDV2
Expression *resolveAliasThis(Scope *sc, Expression *e);
Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope);
int checkPostblit(Loc loc, Type *t);
#endif
struct ArrayExp *resolveOpDollar(Scope *sc, struct ArrayExp *ae);
struct SliceExp *resolveOpDollar(Scope *sc, struct SliceExp *se);
Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc);
/* Interpreter: what form of return value expression is required?
*/
@@ -132,8 +137,9 @@ struct Expression : Object
void print();
char *toChars();
virtual void dump(int indent);
void error(const char *format, ...) IS_PRINTF(2);
void warning(const char *format, ...) IS_PRINTF(2);
void error(const char *format, ...);
void warning(const char *format, ...);
void deprecation(const char *format, ...);
virtual int rvalue();
static Expression *combine(Expression *e1, Expression *e2);
@@ -166,6 +172,8 @@ struct Expression : Object
void checkPurity(Scope *sc, FuncDeclaration *f);
void checkPurity(Scope *sc, VarDeclaration *v, Expression *e1);
void checkSafety(Scope *sc, FuncDeclaration *f);
void checkModifiable(Scope *sc);
virtual int checkCtorInit(Scope *sc);
virtual Expression *checkToBoolean(Scope *sc);
virtual Expression *addDtorHook(Scope *sc);
Expression *checkToPointer();
@@ -176,7 +184,7 @@ struct Expression : Object
Expression *toDelegate(Scope *sc, Type *t);
virtual Expression *optimize(int result);
virtual Expression *optimize(int result, bool keepLvalue = false);
#define WANTflags 1
#define WANTvalue 2
// A compile-time result is required. Give an error if not possible
@@ -376,6 +384,7 @@ struct ThisExp : Expression
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
@@ -477,7 +486,7 @@ struct TupleExp : Expression
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void checkEscape();
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *castTo(Scope *sc, Type *t);
#if IN_DMD
@@ -507,7 +516,7 @@ struct ArrayLiteralExp : Expression
StringExp *toString();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
@@ -542,7 +551,7 @@ struct AssocArrayLiteralExp : Expression
#endif
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
@@ -571,6 +580,7 @@ struct StructLiteralExp : Expression
size_t soffset; // offset from start of s
int fillHoles; // fill alignment 'holes' with zero
bool ownedByCtfe; // true = created in CTFE
int ctorinit;
StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL);
@@ -581,7 +591,7 @@ struct StructLiteralExp : Expression
int getFieldIndex(Type *type, unsigned offset);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
@@ -614,7 +624,7 @@ struct TypeExp : Expression
Expression *semantic(Scope *sc);
int rvalue();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
@@ -669,7 +679,8 @@ struct NewExp : Expression
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
MATCH implicitConvTo(Type *t);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
@@ -753,13 +764,14 @@ struct VarExp : SymbolExp
VarExp(Loc loc, Declaration *var, int hasOverloads = 0);
int equals(Object *o);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void dump(int indent);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -917,7 +929,7 @@ struct UnaExp : Expression
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
void dump(int indent);
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *));
@@ -943,15 +955,15 @@ struct BinExp : Expression
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *scaleFactor(Scope *sc);
Expression *typeCombine(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
int isunsigned();
Expression *incompatibleTypes();
void dump(int indent);
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *));
Expression *interpretCommon2(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Loc, TOK, Type *, Expression *, Expression *));
Expression *interpretCompareCommon(InterState *istate, CtfeGoal goal,
int (*fp)(Loc, TOK, Expression *, Expression *));
Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
Expression *interpretFourPointerRelation(InterState *istate, CtfeGoal goal);
@@ -1050,10 +1062,11 @@ struct DotVarExp : UnaExp
DotVarExp(Loc loc, Expression *e, Declaration *var, int hasOverloads = 0);
Expression *semantic(Scope *sc);
int checkCtorInit(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
@@ -1134,7 +1147,7 @@ struct CallExp : UnaExp
int apply(apply_fp_t fp, void *param);
Expression *resolveUFCS(Scope *sc);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
@@ -1168,7 +1181,7 @@ struct AddrExp : UnaExp
#endif
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_LLVM
DValue* toElem(IRState* irs);
@@ -1181,15 +1194,16 @@ struct PtrExp : UnaExp
PtrExp(Loc loc, Expression *e);
PtrExp(Loc loc, Expression *e, Type *t);
Expression *semantic(Scope *sc);
int isLvalue();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
// For operator overloading
@@ -1205,7 +1219,7 @@ struct NegExp : UnaExp
{
NegExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1236,7 +1250,7 @@ struct ComExp : UnaExp
{
ComExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1258,7 +1272,7 @@ struct NotExp : UnaExp
{
NotExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
#if IN_DMD
@@ -1274,7 +1288,7 @@ struct BoolExp : UnaExp
{
BoolExp(Loc loc, Expression *e, Type *type);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
#if IN_DMD
@@ -1313,7 +1327,7 @@ struct CastExp : UnaExp
Expression *semantic(Scope *sc);
MATCH implicitConvTo(Type *t);
IntRange getIntRange();
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -1364,12 +1378,13 @@ struct SliceExp : UnaExp
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void dump(int indent);
#if IN_DMD
@@ -1391,7 +1406,7 @@ struct ArrayLengthExp : UnaExp
{
ArrayLengthExp(Loc loc, Expression *e1);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
@@ -1444,6 +1459,7 @@ struct CommaExp : BinExp
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
IntRange getIntRange();
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
@@ -1452,7 +1468,7 @@ struct CommaExp : BinExp
MATCH implicitConvTo(Type *t);
Expression *addDtorHook(Scope *sc);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1472,11 +1488,12 @@ struct IndexExp : BinExp
IndexExp(Loc loc, Expression *e1, Expression *e2);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
int checkCtorInit(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *doInline(InlineDoState *ids);
@@ -1604,7 +1621,7 @@ struct AddExp : BinExp
{
AddExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1629,7 +1646,7 @@ struct MinExp : BinExp
{
MinExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1653,7 +1670,7 @@ struct CatExp : BinExp
{
CatExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
// For operator overloading
@@ -1673,7 +1690,7 @@ struct MulExp : BinExp
{
MulExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1697,7 +1714,7 @@ struct DivExp : BinExp
{
DivExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1720,7 +1737,7 @@ struct ModExp : BinExp
{
ModExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1744,7 +1761,7 @@ struct PowExp : BinExp
{
PowExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1767,7 +1784,7 @@ struct ShlExp : BinExp
{
ShlExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
IntRange getIntRange();
@@ -1788,7 +1805,7 @@ struct ShrExp : BinExp
{
ShrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
IntRange getIntRange();
@@ -1809,7 +1826,7 @@ struct UshrExp : BinExp
{
UshrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
IntRange getIntRange();
@@ -1830,7 +1847,7 @@ struct AndExp : BinExp
{
AndExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1854,7 +1871,7 @@ struct OrExp : BinExp
{
OrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1879,7 +1896,7 @@ struct XorExp : BinExp
{
XorExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1906,7 +1923,7 @@ struct OrOrExp : BinExp
Expression *semantic(Scope *sc);
Expression *checkToBoolean(Scope *sc);
int isBit();
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1923,7 +1940,7 @@ struct AndAndExp : BinExp
Expression *semantic(Scope *sc);
Expression *checkToBoolean(Scope *sc);
int isBit();
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1938,7 +1955,7 @@ struct CmpExp : BinExp
{
CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
@@ -1996,7 +2013,7 @@ struct EqualExp : BinExp
{
EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
@@ -2021,7 +2038,7 @@ struct IdentityExp : BinExp
IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
int isBit();
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -2042,10 +2059,11 @@ struct CondExp : BinExp
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void checkEscapeRef();
int checkCtorInit(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -2157,9 +2175,9 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr);
// Const-folding functions used by CTFE
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex);
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex);
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex);
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex);
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex);
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex);
int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len);
int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len);
+252 -125
View File
@@ -94,8 +94,11 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
#if DMDV2
builtin = BUILTINunknown;
tookAddressOf = 0;
requiresClosure = false;
flags = 0;
#endif
returns = NULL;
#if IN_LLVM
// LDC
isArrayOp = false;
@@ -228,10 +231,23 @@ void FuncDeclaration::semantic(Scope *sc)
storage_class |= sc->stc & ~STCref;
ad = isThis();
if (ad)
{
storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
if (StructDeclaration *sd = ad->isStructDeclaration())
sd->makeNested();
}
//printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
FuncLiteralDeclaration *fld = isFuncLiteralDeclaration();
if (fld && fld->treq)
linkage = ((TypeFunction *)fld->treq->nextOf())->linkage;
else
linkage = sc->linkage;
protection = sc->protection;
userAttributes = sc->userAttributes;
if (!originalType)
originalType = type;
if (!type->deco)
@@ -250,6 +266,8 @@ void FuncDeclaration::semantic(Scope *sc)
if (isCtorDeclaration())
sc->flags |= SCOPEctor;
sc->linkage = linkage;
/* Apply const, immutable, wild and shared storage class
* to the function type. Do this before type semantic.
*/
@@ -318,9 +336,6 @@ void FuncDeclaration::semantic(Scope *sc)
f = (TypeFunction *)(type);
size_t nparams = Parameter::dim(f->parameters);
linkage = sc->linkage;
protection = sc->protection;
/* Purity and safety can be inferred for some functions by examining
* the function body.
*/
@@ -411,8 +426,8 @@ void FuncDeclaration::semantic(Scope *sc)
#endif
isDtorDeclaration() ||
isInvariantDeclaration() ||
isUnitTestDeclaration() || isNewDeclaration() || isDelete())
error("constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface %s", id->toChars());
isNewDeclaration() || isDelete())
error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface %s", id->toChars());
if (fbody && isVirtual())
error("function body is not abstract in interface %s", id->toChars());
}
@@ -424,7 +439,7 @@ void FuncDeclaration::semantic(Scope *sc)
cd = parent->isClassDeclaration();
if (cd)
{ int vi;
{ size_t vi;
CtorDeclaration *ctor;
DtorDeclaration *dtor;
InvariantDeclaration *inv;
@@ -539,7 +554,7 @@ void FuncDeclaration::semantic(Scope *sc)
doesoverride = TRUE;
#if DMDV2
if (!isOverride())
warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
::deprecation(loc, "overriding base class function without using override attribute is deprecated (%s overrides %s)", toPrettyChars(), fdv->toPrettyChars());
#endif
FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration();
@@ -601,7 +616,7 @@ void FuncDeclaration::semantic(Scope *sc)
* If this function is covariant with any members of those interface
* functions, set the tintro.
*/
for (int i = 0; i < cd->interfaces_dim; i++)
for (size_t i = 0; i < cd->interfaces_dim; i++)
{
BaseClass *b = cd->interfaces[i];
vi = findVtblIndex((Dsymbols *)&b->base->vtbl, b->base->vtbl.dim);
@@ -688,7 +703,7 @@ void FuncDeclaration::semantic(Scope *sc)
/* Go through all the interface bases.
* Disallow overriding any final functions in the interface(s).
*/
for (int i = 0; i < cd->interfaces_dim; i++)
for (size_t i = 0; i < cd->interfaces_dim; i++)
{
BaseClass *b = cd->interfaces[i];
if (b->base)
@@ -770,32 +785,6 @@ void FuncDeclaration::semantic(Scope *sc)
}
}
if (ident == Id::assign && (sd || cd))
{ // Disallow identity assignment operator.
// opAssign(...)
if (nparams == 0)
{ if (f->varargs == 1)
goto Lassignerr;
}
else
{
Parameter *arg0 = Parameter::getNth(f->parameters, 0);
Type *t0 = arg0->type->toBasetype();
Type *tb = sd ? sd->type : cd->type;
if (arg0->type->implicitConvTo(tb) ||
(sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb))
)
{
if (nparams == 1)
goto Lassignerr;
Parameter *arg1 = Parameter::getNth(f->parameters, 1);
if (arg1->defaultArg)
goto Lassignerr;
}
}
}
if (isVirtual() && semanticRun != PASSsemanticdone)
{
/* Rewrite contracts as nested functions, then call them.
@@ -905,14 +894,6 @@ Ldone:
scope = new Scope(*sc);
scope->setNoFree();
return;
Lassignerr:
if (sd)
{
sd->hasIdentityAssign = 1; // don't need to generate it
goto Ldone;
}
error("identity assignment operator overload is illegal");
}
void FuncDeclaration::semantic2(Scope *sc)
@@ -940,7 +921,7 @@ void FuncDeclaration::semantic3(Scope *sc)
//{ static int x; if (++x == 2) *(char*)0=0; }
//printf("\tlinkage = %d\n", sc->linkage);
//printf(" sc->incontract = %d\n", sc->incontract);
//printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract));
if (semanticRun >= PASSsemantic3)
return;
semanticRun = PASSsemantic3;
@@ -954,12 +935,14 @@ void FuncDeclaration::semantic3(Scope *sc)
if (!type || type->ty != Tfunction)
return;
f = (TypeFunction *)(type);
if (!inferRetType && f->next->ty == Terror)
return;
#if 0
// Check the 'throws' clause
if (fthrows)
{
for (int i = 0; i < fthrows->dim; i++)
for (size_t i = 0; i < fthrows->dim; i++)
{
Type *t = (*fthrows)[i];
@@ -978,7 +961,7 @@ void FuncDeclaration::semantic3(Scope *sc)
if (frequire)
{
for (int i = 0; i < foverrides.dim; i++)
for (size_t i = 0; i < foverrides.dim; i++)
{
FuncDeclaration *fdv = foverrides[i];
@@ -1019,14 +1002,16 @@ void FuncDeclaration::semantic3(Scope *sc)
sc2->protection = PROTpublic;
sc2->explicitProtection = 0;
sc2->structalign = STRUCTALIGN_DEFAULT;
sc2->incontract = 0;
#if !IN_LLVM
sc2->tf = NULL;
#else
sc2->flags = sc->flags & ~SCOPEcontract;
#if IN_LLVM
sc2->enclosingFinally = NULL;
sc2->enclosingScopeExit = NULL;
#else
sc2->tf = NULL;
#endif
sc2->noctor = 0;
sc2->speculative = sc->speculative || isSpeculative() != NULL;
sc2->userAttributes = NULL;
// Declare 'this'
AggregateDeclaration *ad = isThis();
@@ -1051,7 +1036,7 @@ void FuncDeclaration::semantic3(Scope *sc)
Type *t;
#if !IN_GCC && !IN_LLVM
if (global.params.is64bit)
if (global.params.is64bit && !global.params.isWindows)
{ // Declare save area for varargs registers
Type *t = new TypeIdentifier(loc, Id::va_argsave_t);
t = t->semantic(loc, sc);
@@ -1115,8 +1100,8 @@ void FuncDeclaration::semantic3(Scope *sc)
// This is important if it turned into a tuple.
// In particular, the empty tuple should be handled or the
// next parameter will be skipped.
// FIXME: Maybe we only need to do this for tuples,
// and can add tuple.length after decrement?
// LDC_FIXME: Maybe we only need to do this for tuples,
// and can add tuple.length after decrement?
i--;
}
}
@@ -1336,7 +1321,7 @@ void FuncDeclaration::semantic3(Scope *sc)
sym->parent = sc2->scopesym;
sc2 = sc2->push(sym);
AggregateDeclaration *ad = isAggregateMember();
AggregateDeclaration *ad = isAggregateMember2();
/* If this is a class constructor
*/
@@ -1363,7 +1348,19 @@ void FuncDeclaration::semantic3(Scope *sc)
((TypeFunction *)type)->next = Type::tvoid;
//type = type->semantic(loc, sc); // Removed with 6902
}
f = (TypeFunction *)type;
else if (returns && f->next->ty != Tvoid)
{
for (size_t i = 0; i < returns->dim; i++)
{ Expression *exp = (*returns)[i]->exp;
if (!f->next->invariantOf()->equals(exp->type->invariantOf()))
{ exp = exp->castTo(sc2, f->next);
exp = exp->optimize(WANTvalue);
(*returns)[i]->exp = exp;
}
//printf("[%d] %s %s\n", i, exp->type->toChars(), exp->toChars());
}
}
assert(type == f);
}
if (isStaticCtorDeclaration())
@@ -1389,6 +1386,15 @@ void FuncDeclaration::semantic3(Scope *sc)
if (isCtorDeclaration() && ad)
{
#if DMDV2
// Check for errors related to 'nothrow'.
int nothrowErrors = global.errors;
int blockexit = fbody->blockExit(f->isnothrow);
if (f->isnothrow && (global.errors != nothrowErrors) )
error("'%s' is nothrow yet may throw", toChars());
if (flags & FUNCFLAGnothrowInprocess)
f->isnothrow = !(blockexit & BEthrow);
#endif
//printf("callSuper = x%x\n", sc2->callSuper);
ClassDeclaration *cd = ad->isClassDeclaration();
@@ -1408,9 +1414,15 @@ void FuncDeclaration::semantic3(Scope *sc)
* as delegating calls to other constructors
*/
if (v->isCtorinit() && !v->type->isMutable() && cd)
error("missing initializer for final field %s", v->toChars());
{
OutBuffer buf;
MODtoBuffer(&buf, v->type->mod);
error("missing initializer for %s field %s", buf.toChars(), v->toChars());
}
else if (v->storage_class & STCnodefaultctor)
error("field %s must be initialized in constructor", v->toChars());
else if (v->type->needsNested())
error("field %s must be initialized in constructor, because it is nested struct", v->toChars());
}
}
}
@@ -1427,7 +1439,10 @@ void FuncDeclaration::semantic3(Scope *sc)
e = e->trySemantic(sc2);
if (!e)
error("no match for implicit super() call in constructor");
{
const char* impGen = ((CtorDeclaration*)this)->isImplicit ? "implicitly generated " : "";
error("no match for implicit super() call in %sconstructor", impGen);
}
else
{
Statement *s = new ExpStatement(0, e);
@@ -1453,15 +1468,11 @@ void FuncDeclaration::semantic3(Scope *sc)
#if DMDV2
// Check for errors related to 'nothrow'.
int nothrowErrors = global.errors;
int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru;
int blockexit = fbody->blockExit(f->isnothrow);
if (f->isnothrow && (global.errors != nothrowErrors) )
error("'%s' is nothrow yet may throw", toChars());
if (flags & FUNCFLAGnothrowInprocess)
{
flags &= ~FUNCFLAGnothrowInprocess;
if (!(blockexit & BEthrow))
f->isnothrow = TRUE;
}
f->isnothrow = !(blockexit & BEthrow);
int offend = blockexit & BEfallthru;
#endif
@@ -1510,18 +1521,14 @@ void FuncDeclaration::semantic3(Scope *sc)
ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc2->scopesym;
sc2 = sc2->push(sym);
sc2->incontract++;
sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire;
// BUG: need to error if accessing out parameters
// BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
// BUG: verify that all in and ref parameters are read
DsymbolTable *labtab_save = labtab;
labtab = NULL; // so in contract can't refer to out/body labels
freq = freq->semantic(sc2);
labtab = labtab_save;
sc2->incontract--;
sc2 = sc2->pop();
if (!global.params.useIn)
@@ -1540,16 +1547,12 @@ void FuncDeclaration::semantic3(Scope *sc)
buildResultVar();
sc2 = scout; //push
sc2->incontract++;
sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure;
// BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
DsymbolTable *labtab_save = labtab;
labtab = NULL; // so out contract can't refer to in/body labels
fens = fens->semantic(sc2);
labtab = labtab_save;
sc2->incontract--;
sc2 = sc2->pop();
if (!global.params.useOut)
@@ -1586,7 +1589,7 @@ void FuncDeclaration::semantic3(Scope *sc)
v_argptr->init = new VoidInitializer(loc);
#else
Type *t = argptr->type;
if (global.params.is64bit)
if (global.params.is64bit && !global.params.isWindows)
{ // Initialize _argptr to point to v_argsave
Expression *e1 = new VarExp(0, argptr);
Expression *e = new SymOffExp(0, v_argsave, 6*8 + 8*16);
@@ -1599,12 +1602,13 @@ void FuncDeclaration::semantic3(Scope *sc)
{ // Initialize _argptr to point past non-variadic arg
VarDeclaration *p;
unsigned offset = 0;
Expression *e;
Expression *e1 = new VarExp(0, argptr);
// Find the last non-ref parameter
if (parameters && parameters->dim)
{
int lastNonref = parameters->dim -1;
size_t lastNonref = parameters->dim -1;
p = (*parameters)[lastNonref];
/* The trouble with out and ref parameters is that taking
* the address of it doesn't work, because later processing
@@ -1612,9 +1616,8 @@ void FuncDeclaration::semantic3(Scope *sc)
*/
while (p->storage_class & (STCout | STCref))
{
--lastNonref;
offset += PTRSIZE;
if (lastNonref < 0)
if (lastNonref-- == 0)
{
p = v_arguments;
break;
@@ -1624,15 +1627,32 @@ void FuncDeclaration::semantic3(Scope *sc)
}
else
p = v_arguments; // last parameter is _arguments[]
if (global.params.is64bit && global.params.isWindows)
{ offset += PTRSIZE;
if (p->storage_class & STClazy)
{
/* Necessary to offset the extra level of indirection the Win64
* ABI demands
*/
e = new SymOffExp(0,p,0);
e->type = Type::tvoidptr;
e = new AddrExp(0, e);
e->type = Type::tvoidptr;
e = new AddExp(0, e, new IntegerExp(offset));
e->type = Type::tvoidptr;
goto L1;
}
}
else if (p->storage_class & STClazy)
// If the last parameter is lazy, it's the size of a delegate
offset += PTRSIZE * 2;
else
offset += p->type->size();
offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size
Expression *e = new SymOffExp(0, p, offset);
e = new SymOffExp(0, p, offset);
e->type = Type::tvoidptr;
//e = e->semantic(sc);
L1:
e = new AssignExp(0, e1, e);
e->type = t;
a->push(new ExpStatement(0, e));
@@ -1669,7 +1689,6 @@ void FuncDeclaration::semantic3(Scope *sc)
else if (fpreinv)
freq = new CompoundStatement(0, freq, fpreinv);
freq->incontract = 1;
a->push(freq);
}
@@ -1745,6 +1764,13 @@ void FuncDeclaration::semantic3(Scope *sc)
if (e)
{ Statement *s = new ExpStatement(0, e);
s = s->semantic(sc2);
int nothrowErrors = global.errors;
bool isnothrow = f->isnothrow & !(flags & FUNCFLAGnothrowInprocess);
int blockexit = s->blockExit(isnothrow);
if (f->isnothrow && (global.errors != nothrowErrors) )
error("'%s' is nothrow yet may throw", toChars());
if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
f->isnothrow = FALSE;
if (fbody->blockExit(f->isnothrow) == BEfallthru)
fbody = new CompoundStatement(0, fbody, s);
else
@@ -1752,6 +1778,8 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
}
// from this point on all possible 'throwers' are checked
flags &= ~FUNCFLAGnothrowInprocess;
#endif
#if 1
@@ -1764,7 +1792,7 @@ void FuncDeclaration::semantic3(Scope *sc)
if (cd)
{
#if TARGET_WINDOS
if (/*config.flags2 & CFG2seh &&*/ // always on for WINDOS
if (!global.params.is64bit &&
!isStatic() && !fbody->usesEH())
{
/* The back end uses the "jmonitor" hack for syncing;
@@ -1821,7 +1849,16 @@ void FuncDeclaration::semantic3(Scope *sc)
}
if (global.gag && global.errors != nerrors)
{
/* Errors happened when compiling this function.
*/
semanticRun = PASSsemanticdone; // Ensure errors get reported again
/* Except that re-running semantic3() doesn't always produce errors a second
* time through.
* See Bugzilla 8348
* Need a better way to deal with this than gagging.
*/
}
else
{
semanticRun = PASSsemantic3done;
@@ -1963,7 +2000,9 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writebyte('{');
buf->writenl();
buf->level++;
fbody->toCBuffer(buf, hgs);
buf->level--;
buf->writebyte('}');
buf->writenl();
}
@@ -2063,7 +2102,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf, Expressions *params)
* handler block, so it is always at the same offset from EBP.
*/
#endif
for (int i = 0; i < foverrides.dim; i++)
for (size_t i = 0; i < foverrides.dim; i++)
{
FuncDeclaration *fdv = foverrides[i];
@@ -2121,7 +2160,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Expressions *params)
* list for the 'this' pointer, something that would need an unknown amount
* of tweaking of various parts of the compiler that I'd rather leave alone.
*/
for (int i = 0; i < foverrides.dim; i++)
for (size_t i = 0; i < foverrides.dim; i++)
{
FuncDeclaration *fdv = foverrides[i];
@@ -2142,7 +2181,42 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Expressions *params)
{
//printf("fdv->fensure: %s\n", fdv->fensure->toChars());
// Make the call: __ensure(result)
Expression *eresult = NULL;
if (outId)
{
#if IN_LLVM
eresult = (*params)[0];
#else
eresult = new IdentifierExp(loc, outId);
#endif
Type *t1 = fdv->type->nextOf()->toBasetype();
#if IN_LLVM
// We actually check for matching types in CommaExp::toElem,
// 'testcontract' breaks without this.
t1 = t1->constOf();
#endif
Type *t2 = this->type->nextOf()->toBasetype();
int offset;
if (t1->isBaseOf(t2, &offset) && offset != 0)
{
/* Making temporary reference variable is necessary
* to match offset difference in covariant return.
* See bugzilla 5204.
*/
ExpInitializer *ei = new ExpInitializer(0, eresult);
VarDeclaration *v = new VarDeclaration(0, t1, Lexer::uniqueId("__covres"), ei);
DeclarationExp *de = new DeclarationExp(0, v);
VarExp *ve = new VarExp(0, v);
eresult = new CommaExp(0, de, ve);
}
}
#if IN_LLVM
if (eresult)
(*params)[0] = eresult;
Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure, 0), params);
#else
Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure, 0), eresult);
#endif
Statement *s2 = new ExpStatement(loc, e);
if (sf)
@@ -2462,6 +2536,8 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t, Module* from)
/********************************************
* Decide which function matches the arguments best.
* flags 1: do not issue error message on no match, just return NULL
* 2: do not issue error on ambiguous matches and need explicit this
*/
struct Param2
@@ -2530,6 +2606,23 @@ int fp2(void *param, FuncDeclaration *f)
if (c1 < c2)
goto LlastIsBetter;
}
/* If the two functions are the same function, like:
* int foo(int);
* int foo(int x) { ... }
* then pick the one with the body.
*/
if (tf->equals(m->lastf->type) &&
f->storage_class == m->lastf->storage_class &&
f->parent == m->lastf->parent &&
f->protection == m->lastf->protection &&
f->linkage == m->lastf->linkage)
{
if (f->fbody && !m->lastf->fbody)
goto LfIsBetter;
else if (!f->fbody && m->lastf->fbody)
goto LlastIsBetter;
}
#endif
Lambiguous:
m->nextf = f;
@@ -2596,17 +2689,14 @@ if (arguments)
OutBuffer buf;
buf.writeByte('(');
if (arguments)
if (arguments && arguments->dim)
{
HdrGenState hgs;
argExpTypesToCBuffer(&buf, arguments, &hgs);
buf.writeByte(')');
if (ethis)
ethis->type->modToBuffer(&buf);
}
else
buf.writeByte(')');
buf.writeByte(')');
if (ethis)
ethis->type->modToBuffer(&buf);
if (m.last == MATCHnomatch)
{
@@ -2627,14 +2717,16 @@ if (arguments)
}
else
{
if ((flags & 2) && m.lastf->needThis() && !ethis)
return m.lastf;
#if 1
TypeFunction *t1 = (TypeFunction *)m.lastf->type;
TypeFunction *t2 = (TypeFunction *)m.nextf->type;
error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s(%d): %s%s\nand:\n\t%s(%d): %s%s",
buf.toChars(),
m.lastf->toPrettyChars(), Parameter::argsTypesToChars(t1->parameters, t1->varargs),
m.nextf->toPrettyChars(), Parameter::argsTypesToChars(t2->parameters, t2->varargs));
m.lastf->loc.filename, m.lastf->loc.linnum, m.lastf->toPrettyChars(), Parameter::argsTypesToChars(t1->parameters, t1->varargs),
m.nextf->loc.filename, m.nextf->loc.linnum, m.nextf->toPrettyChars(), Parameter::argsTypesToChars(t2->parameters, t2->varargs));
#else
error(loc, "overloads %s and %s both match argument list for %s",
m.lastf->type->toChars(),
@@ -2693,7 +2785,7 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
*/
Expressions args;
args.setDim(nfparams);
for (int u = 0; u < nfparams; u++)
for (size_t u = 0; u < nfparams; u++)
{
Parameter *p = Parameter::getNth(tf->parameters, u);
Expression *e;
@@ -2807,14 +2899,14 @@ AggregateDeclaration *FuncDeclaration::isMember2()
//printf("\ts = '%s', parent = '%s', kind = %s\n", s->toChars(), s->parent->toChars(), s->parent->kind());
ad = s->isMember();
if (ad)
{
{
break;
}
}
if (!s->parent ||
(!s->parent->isTemplateInstance()))
{
{
break;
}
}
}
//printf("-FuncDeclaration::isMember2() %p\n", ad);
return ad;
@@ -3071,6 +3163,8 @@ enum PURE FuncDeclaration::isPureBypassingInference()
{
if (flags & FUNCFLAGpurityInprocess)
return PUREfwdref;
else if (type->nextOf() == NULL)
return PUREfwdref;
else
return isPure();
}
@@ -3281,25 +3375,46 @@ int FuncDeclaration::needsClosure()
*/
//printf("FuncDeclaration::needsClosure() %s\n", toChars());
for (int i = 0; i < closureVars.dim; i++)
if (requiresClosure)
goto Lyes;
for (size_t i = 0; i < closureVars.dim; i++)
{ VarDeclaration *v = closureVars[i];
assert(v->isVarDeclaration());
//printf("\tv = %s\n", v->toChars());
for (int j = 0; j < v->nestedrefs.dim; j++)
for (size_t j = 0; j < v->nestedrefs.dim; j++)
{ FuncDeclaration *f = v->nestedrefs[j];
assert(f != this);
//printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
if (f->isThis() || f->tookAddressOf)
goto Lyes; // assume f escapes this function's scope
//printf("\t\tf = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
// Look to see if any parents of f that are below this escape
for (Dsymbol *s = f->parent; s && s != this; s = s->parent)
// Look to see if f or any parents of f that are below this escape
for (Dsymbol *s = f; s && s != this; s = s->parent)
{
f = s->isFuncDeclaration();
if (f && (f->isThis() || f->tookAddressOf))
FuncDeclaration *fx = s->isFuncDeclaration();
if (fx && (fx->isThis() || fx->tookAddressOf))
{
//printf("\t\tfx = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", fx->toChars(), fx->isVirtual(), fx->isThis(), fx->tookAddressOf);
/* Mark as needing closure any functions between this and f
*/
for (Dsymbol *sx = fx; sx != this; sx = sx->parent)
{
if (sx != f)
{ FuncDeclaration *fy = sx->isFuncDeclaration();
if (fy && fy->closureVars.dim)
{
/* fy needs a closure if it has closureVars[],
* because the frame pointer in the closure will be accessed.
*/
fy->requiresClosure = true;
}
}
}
goto Lyes;
}
}
}
}
@@ -3312,12 +3427,17 @@ int FuncDeclaration::needsClosure()
Type *tret = ((TypeFunction *)type)->next;
assert(tret);
tret = tret->toBasetype();
//printf("\t\treturning %s\n", tret->toChars());
if (tret->ty == Tclass || tret->ty == Tstruct)
{ Dsymbol *st = tret->toDsymbol(NULL);
//printf("\t\treturning class/struct %s\n", tret->toChars());
for (Dsymbol *s = st->parent; s; s = s->parent)
{
//printf("\t\t\tparent = %s %s\n", s->kind(), s->toChars());
if (s == this)
{ //printf("\t\treturning local %s\n", st->toChars());
goto Lyes;
}
}
}
}
@@ -3414,6 +3534,7 @@ FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOv
assert(!funcalias->isFuncAliasDeclaration());
this->hasOverloads = 0;
}
userAttributes = funcalias->userAttributes;
}
const char *FuncAliasDeclaration::kind()
@@ -3502,6 +3623,7 @@ CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *ty
: FuncDeclaration(loc, endloc, Id::ctor, stc, type)
{
//printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
this->isImplicit = false;
}
Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
@@ -3550,17 +3672,14 @@ void CtorDeclaration::semantic(Scope *sc)
tret = tret->addMod(type->mod);
}
tf->next = tret;
if (!originalType)
originalType = type->syntaxCopy();
type = type->semantic(loc, sc);
#if STRUCTTHISREF
if (ad && ad->isStructDeclaration())
{ if (!originalType)
originalType = type->syntaxCopy();
((TypeFunction *)type)->isref = 1;
}
#endif
if (!originalType)
originalType = type;
// Append:
// return this;
@@ -3578,8 +3697,11 @@ void CtorDeclaration::semantic(Scope *sc)
sc->pop();
// See if it's the default constructor
if (ad && tf->varargs == 0 && Parameter::dim(tf->parameters) == 0)
/* See if it's the default constructor
* But, template constructor should not become a default constructor.
*/
if (ad && tf->varargs == 0 && Parameter::dim(tf->parameters) == 0
&& (!this->parent->isTemplateInstance() || this->parent->isTemplateMixin()))
{
StructDeclaration *sd = ad->isStructDeclaration();
if (sd)
@@ -3592,7 +3714,9 @@ void CtorDeclaration::semantic(Scope *sc)
sd->noDefaultCtor = TRUE;
}
else
{
ad->defaultCtor = this;
}
}
}
@@ -3625,20 +3749,15 @@ int CtorDeclaration::addPostInvariant()
/********************************* PostBlitDeclaration ****************************/
#if DMDV2
PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc)
: FuncDeclaration(loc, endloc, Id::_postblit, stc, NULL)
{
}
PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id)
: FuncDeclaration(loc, endloc, id, STCundefined, NULL)
PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
: FuncDeclaration(loc, endloc, id, stc, NULL)
{
}
Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
{
assert(!s);
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, ident);
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, storage_class, ident);
return FuncDeclaration::syntaxCopy(dd);
}
@@ -4103,7 +4222,7 @@ void InvariantDeclaration::semantic(Scope *sc)
sc = sc->push();
sc->stc &= ~STCstatic; // not a static invariant
sc->stc |= STCconst; // invariant() is always const
sc->incontract++;
sc->flags = (sc->flags & ~SCOPEcontract) | SCOPEinvariant;
sc->linkage = LINKd;
FuncDeclaration::semantic(sc);
@@ -4142,13 +4261,21 @@ void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
* instances per module.
*/
static Identifier *unitTestId()
#if __DMC__ || _MSC_VER
#define snprintf _snprintf
#endif
static Identifier *unitTestId(Loc loc)
{
return Lexer::uniqueId("__unittest");
char name[24];
snprintf(name, 24, "__unittestL%u_", loc.linnum);
return Lexer::uniqueId(name);
}
#if __DMC__ || _MSC_VER
#undef snprintf
#endif
UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
: FuncDeclaration(loc, endloc, unitTestId(), STCundefined, NULL)
: FuncDeclaration(loc, endloc, unitTestId(loc), STCundefined, NULL)
{
}
+1
View File
@@ -51,6 +51,7 @@ void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void Module::genhdrfile()
{
OutBuffer hdrbufr;
hdrbufr.doindent = 1;
hdrbufr.printf("// D import file generated from '%s'", srcfile->toChars());
hdrbufr.writenl();
+1
View File
@@ -28,6 +28,7 @@ struct HdrGenState
int init;
int decl;
} FLinit;
Scope* scope; // Scope when generating ddoc
HdrGenState() { memset(this, 0, sizeof(HdrGenState)); }
};
+1 -1
View File
@@ -28,7 +28,7 @@ struct Identifier : Object
{
int value;
const char *string;
unsigned len;
size_t len;
Identifier(const char *string, int value);
int equals(Object *o);
+3
View File
@@ -352,6 +352,7 @@ Msgtable msgtable[] =
{ "isArithmetic" },
{ "isAssociativeArray" },
{ "isFinalClass" },
{ "isPOD" },
{ "isFloating" },
{ "isIntegral" },
{ "isScalar" },
@@ -367,6 +368,7 @@ Msgtable msgtable[] =
{ "isLazy" },
{ "hasMember" },
{ "identifier" },
{ "getProtection" },
{ "parent" },
{ "getMember" },
{ "getOverloads" },
@@ -378,6 +380,7 @@ Msgtable msgtable[] =
{ "isSame" },
{ "compiles" },
{ "parameters" },
{ "getAttributes" },
};
+20 -13
View File
@@ -169,15 +169,17 @@ void Import::importAll(Scope *sc)
{
if (!mod)
{
load(sc);
mod->importAll(0);
load(sc);
if (mod) // if successfully loaded module
{ mod->importAll(0);
if (!isstatic && !aliasId && !names.dim)
{
if (sc->explicitProtection)
protection = sc->protection;
sc->scopesym->importScope(mod, protection);
}
if (!isstatic && !aliasId && !names.dim)
{
if (sc->explicitProtection)
protection = sc->protection;
sc->scopesym->importScope(mod, protection);
}
}
}
}
@@ -280,7 +282,9 @@ void Import::semantic(Scope *sc)
escapePath(ob, sc->module->srcfile->toChars());
ob->writestring(") : ");
ProtDeclaration::protectionToCBuffer(ob, sc->protection);
// use protection instead of sc->protection because it couldn't be
// resolved yet, see the comment above
ProtDeclaration::protectionToCBuffer(ob, protection);
if (isstatic)
StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
ob->writestring(": ");
@@ -333,10 +337,13 @@ void Import::semantic(Scope *sc)
void Import::semantic2(Scope *sc)
{
//printf("Import::semantic2('%s')\n", toChars());
mod->semantic2();
if (mod->needmoduleinfo)
{ //printf("module5 %s because of %s\n", sc->module->toChars(), mod->toChars());
sc->module->needmoduleinfo = 1;
if (mod)
{
mod->semantic2();
if (mod->needmoduleinfo)
{ //printf("module5 %s because of %s\n", sc->module->toChars(), mod->toChars());
sc->module->needmoduleinfo = 1;
}
}
}
+59 -11
View File
@@ -22,6 +22,7 @@
#include "mtype.h"
#include "hdrgen.h"
#include "template.h"
#include "id.h"
/********************************** Initializer *******************************/
@@ -152,9 +153,11 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
//printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
vars.setDim(field.dim);
t = t->toBasetype();
if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct)
t = t->nextOf()->toBasetype();
if (t->ty == Tstruct)
{
unsigned fieldi = 0;
size_t fieldi = 0;
TypeStruct *ts = (TypeStruct *)t;
ad = ts->sym;
@@ -292,7 +295,7 @@ Expression *StructInitializer::toExpression()
{
(*elements)[i] = NULL;
}
unsigned fieldi = 0;
size_t fieldi = 0;
for (size_t i = 0; i < value.dim; i++)
{
Identifier *id = field[i];
@@ -355,7 +358,20 @@ Expression *StructInitializer::toExpression()
if (!(*elements)[i])
{ // Default initialize
if (vd->init)
(*elements)[i] = vd->init->toExpression();
{
if (vd->scope)
{ // Do deferred semantic analysis
Initializer *i2 = vd->init->syntaxCopy();
i2 = i2->semantic(vd->scope, vd->type, INITinterpret);
(*elements)[i] = i2->toExpression();
if (!global.gag)
{ vd->scope = NULL;
vd->init = i2; // save result
}
}
else
(*elements)[i] = vd->init->toExpression();
}
else
(*elements)[i] = vd->type->defaultInit();
}
@@ -469,8 +485,8 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value)
}
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{ unsigned i;
unsigned length;
{
size_t length;
const unsigned amax = 0x80000000;
//printf("ArrayInitializer::semantic(%s)\n", t->toChars());
@@ -478,6 +494,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
return this;
sem = 1;
type = t;
Initializer *aa = NULL;
t = t->toBasetype();
switch (t->ty)
{
@@ -490,13 +507,18 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
t = ((TypeVector *)t)->basetype;
break;
case Taarray:
// was actually an associative array literal
aa = new ExpInitializer(loc, toAssocArrayLiteral());
return aa->semantic(sc, t, needInterpret);
default:
error(loc, "cannot use array to initialize %s", type->toChars());
goto Lerr;
}
length = 0;
for (i = 0; i < index.dim; i++)
for (size_t i = 0; i < index.dim; i++)
{
Expression *idx = index[i];
if (idx)
@@ -552,8 +574,8 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
}
}
if ((unsigned long) dim * t->nextOf()->size() >= amax)
{ error(loc, "array dimension %u exceeds max of %u", dim, amax / t->nextOf()->size());
if ((uinteger_t) dim * t->nextOf()->size() >= amax)
{ error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size()));
goto Lerr;
}
return this;
@@ -602,7 +624,12 @@ Expression *ArrayInitializer::toExpression()
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index[i])
j = index[i]->toInteger();
{
if (index[i]->op == TOKint64)
j = index[i]->toInteger();
else
goto Lno;
}
if (j >= edim)
edim = j + 1;
}
@@ -881,6 +908,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
}
Type *tb = t->toBasetype();
Type *ti = exp->type->toBasetype();
if (exp->op == TOKtuple &&
expandTuples &&
@@ -893,7 +921,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
* Allow this by doing an explicit cast, which will lengthen the string
* literal.
*/
if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
if (exp->op == TOKstring && tb->ty == Tsarray && ti->ty == Tsarray)
{ StringExp *se = (StringExp *)exp;
if (!se->committed && se->type->ty == Tsarray &&
@@ -905,10 +933,30 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
}
}
// Look for implicit constructor call
if (tb->ty == Tstruct &&
!(ti->ty == Tstruct && tb->toDsymbol(sc) == ti->toDsymbol(sc)) &&
!exp->implicitConvTo(t))
{
StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->ctor)
{ // Rewrite as S().ctor(exp)
Expression *e;
e = new StructLiteralExp(loc, sd, NULL);
e = new DotIdExp(loc, e, Id::ctor);
e = new CallExp(loc, e, exp);
e = e->semantic(sc);
if (needInterpret)
exp = e->ctfeInterpret();
else
exp = e->optimize(WANTvalue);
}
}
// Look for the case of statically initializing an array
// with a single member.
if (tb->ty == Tsarray &&
!tb->nextOf()->equals(exp->type->toBasetype()->nextOf()) &&
!tb->nextOf()->equals(ti->toBasetype()->nextOf()) &&
exp->implicitConvTo(tb->nextOf())
)
{
+1 -1
View File
@@ -107,7 +107,7 @@ struct ArrayInitializer : Initializer
{
Expressions index; // indices
Initializers value; // of Initializer *'s
unsigned dim; // length of array being initialized
size_t dim; // length of array being initialized
Type *type; // type that array will be used to initialize
int sem; // !=0 if semantic() is run
-56
View File
@@ -1134,62 +1134,6 @@ Statement *ReturnStatement::inlineScan(InlineScanState *iss)
FuncDeclaration *func = iss->fd;
TypeFunction *tf = (TypeFunction *)(func->type);
/* Postblit call on return statement is processed in glue layer
* (Because NRVO may eliminate the copy), but inlining may remove
* ReturnStatement itself. To keep semantics we should insert
* temporary variable for postblit call.
* This is mostly the same as ReturnStatement::toIR.
*/
enum RET retmethod = tf->retStyle();
if (retmethod == RETstack)
{
if (func->nrvo_can && func->nrvo_var)
;
else
{
Type *tb = exp->type->toBasetype();
if (exp->isLvalue() && tb->ty == Tstruct)
{ StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->postblit)
{ FuncDeclaration *fd = sd->postblit;
if (fd->storage_class & STCdisable)
{
fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
}
/* Rewirte exp as:
* (__inlinectmp = exp), __inlinectmp.__postblit(), __inlinectmp
* And, __inlinectmp is marked as rvalue (See STCtemp comment)
*/
ExpInitializer *ei = new ExpInitializer(loc, exp);
Identifier* tmp = Identifier::generateId("__inlinectmp");
VarDeclaration *v = new VarDeclaration(loc, exp->type, tmp, ei);
v->storage_class = STCtemp;
v->linkage = LINKd;
v->parent = func;
VarExp *ve = new VarExp(loc, v);
ve->type = exp->type;
ei->exp = new ConstructExp(loc, ve, exp);
ei->exp->type = exp->type;
DeclarationExp *de = new DeclarationExp(0, v);
de->type = Type::tvoid;
Expression *e = new DotVarExp(ve->loc, ve, sd->postblit, 0);
e->type = sd->postblit->type;
e = new CallExp(ve->loc, e);
e->type = Type::tvoid;
exp = Expression::combine(de, e);
exp = Expression::combine(exp, ve);
}
}
}
}
}
return this;
}
+392 -1867
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -214,6 +214,7 @@ SignExtendedNumber SignExtendedNumber::operator<<(const SignExtendedNumber& a) c
// compute base-2 log of 'v' to determine the maximum allowed bits to shift.
// Ref: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
// Why is this a size_t? Looks like a bug.
size_t r, s;
r = (v > 0xFFFFFFFFULL) << 5; v >>= r;
+5 -1
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by KennyTM
// http://www.digitalmars.com
@@ -44,6 +44,10 @@ struct SignExtendedNumber
/// Get the minimum or maximum value of a sign-extended number.
static SignExtendedNumber extreme(bool minimum);
// These names probably shouldn't be used anyway, as they are common macros
#undef max
#undef min
static SignExtendedNumber max();
static SignExtendedNumber min() { return SignExtendedNumber(0, true); }
+19 -8
View File
@@ -11,6 +11,7 @@
#include "mtype.h"
#include "declaration.h"
#include "irstate.h"
#include "statement.h"
IRState::IRState(IRState *irs, Statement *s)
{
@@ -108,16 +109,26 @@ IRState::IRState(Module *m, Dsymbol *s)
block *IRState::getBreakBlock(Identifier *ident)
{
IRState *bc;
for (bc = this; bc; bc = bc->prev)
{
if (ident)
{
if (bc->prev && bc->prev->ident == ident)
if (ident) {
Statement *related = NULL;
block *ret = NULL;
for (bc = this; bc; bc = bc->prev) {
// The label for a breakBlock may actually be some levels up (e.g.
// on a try/finally wrapping a loop). We'll see if this breakBlock
// is the one to return once we reach that outer statement (which
// in many cases will be this same statement).
if (bc->breakBlock) {
related = bc->statement->getRelatedLabeled();
ret = bc->breakBlock;
}
if (bc->statement == related && bc->prev->ident == ident)
return ret;
}
} else {
for (bc = this; bc; bc = bc->prev) {
if (bc->breakBlock)
return bc->breakBlock;
}
else if (bc->breakBlock)
return bc->breakBlock;
}
return NULL;
}
+5
View File
@@ -20,7 +20,12 @@ struct Identifier;
struct Symbol;
struct FuncDeclaration;
struct Blockx;
#if IN_LLVM
struct DValue;
typedef DValue elem;
#else
struct elem;
#endif
#include "arraytypes.h"
struct IRState
+1 -2
View File
@@ -44,7 +44,6 @@ const char Ptype[] = "type";
const char Pcomment[] = "comment";
const char Pmembers[] = "members";
const char Pprotection[] = "protection";
const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};
void JsonRemoveComma(OutBuffer *buf);
@@ -74,7 +73,7 @@ void json_generate(Modules *modules)
}
else if (arg[0] == '-' && arg[1] == 0)
{ // Write to stdout; assume it succeeds
int n = fwrite(buf.data, 1, buf.offset, stdout);
size_t n = fwrite(buf.data, 1, buf.offset, stdout);
assert(n == buf.offset); // keep gcc happy about return values
return;
}
+27 -23
View File
@@ -41,7 +41,7 @@
extern "C" char * __cdecl __locale_decpoint;
#endif
extern int HtmlNamedEntity(unsigned char *p, int length);
extern int HtmlNamedEntity(unsigned char *p, size_t length);
#define LS 0x2028 // UTF line separator
#define PS 0x2029 // UTF paragraph separator
@@ -127,11 +127,11 @@ const char *Token::toChars()
break;
case TOKint64v:
sprintf(buffer,"%lldL",(intmax_t)int64value);
sprintf(buffer,"%lldL",(longlong)int64value);
break;
case TOKuns64v:
sprintf(buffer,"%lluUL",(uintmax_t)uns64value);
sprintf(buffer,"%lluUL",(ulonglong)uns64value);
break;
#ifdef IN_GCC
@@ -249,7 +249,7 @@ StringTable Lexer::stringtable;
OutBuffer Lexer::stringbuffer;
Lexer::Lexer(Module *mod,
unsigned char *base, unsigned begoffset, unsigned endoffset,
unsigned char *base, size_t begoffset, size_t endoffset,
int doDocComment, int commentToken)
: loc(mod, 1)
{
@@ -321,6 +321,14 @@ void Lexer::error(Loc loc, const char *format, ...)
va_end(ap);
}
void Lexer::deprecation(const char *format, ...)
{
va_list ap;
va_start(ap, format);
::vdeprecation(tokenLoc(), format, ap);
va_end(ap);
}
TOK Lexer::nextToken()
{ Token *t;
@@ -576,8 +584,7 @@ void Lexer::scan(Token *t)
t->postfix = 0;
t->value = TOKstring;
#if DMDV2
if (!global.params.useDeprecated)
error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", (int)(p - pstart), pstart, (int)(p - pstart), pstart);
error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart);
#endif
return;
}
@@ -1294,7 +1301,7 @@ unsigned Lexer::escapeSequence()
c = v;
}
else
error("undefined escape hex sequence \\%c\n",c);
error("undefined escape hex sequence \\%c",c);
break;
case '&': // named character entity
@@ -1343,7 +1350,7 @@ unsigned Lexer::escapeSequence()
error("0%03o is larger than a byte", c);
}
else
error("undefined escape sequence \\%c\n",c);
error("undefined escape sequence \\%c",c);
break;
}
return c;
@@ -1943,7 +1950,7 @@ TOK Lexer::number(Token *t)
if (p[1] == '.') // .. is a separate token
goto done;
#if DMDV2
if (isalpha(p[1]) || p[1] == '_')
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
goto done;
#endif
case 'i':
@@ -1985,7 +1992,7 @@ TOK Lexer::number(Token *t)
if (c == '.' && p[1] != '.')
{
#if DMDV2
if (isalpha(p[1]) || p[1] == '_')
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
goto done;
#endif
goto real;
@@ -2146,9 +2153,6 @@ done:
f = FLAGS_unsigned;
goto L1;
case 'l':
if (1 || !global.params.useDeprecated)
error("'l' suffix is deprecated, use 'L' instead");
case 'L':
f = FLAGS_long;
L1:
@@ -2164,8 +2168,8 @@ done:
}
#if DMDV2
if (state == STATE_octal && n >= 8 && !global.params.useDeprecated)
error("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead",
if (state == STATE_octal && n >= 8)
deprecation("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead",
n, p - psuffix, psuffix, n, p - psuffix, psuffix);
#endif
@@ -2404,8 +2408,7 @@ done:
break;
case 'l':
if (!global.params.useDeprecated)
error("'l' suffix is deprecated, use 'L' instead");
error("'l' suffix is deprecated, use 'L' instead");
case 'L':
result = TOKfloat80v;
p++;
@@ -2413,7 +2416,7 @@ done:
}
if (*p == 'i' || *p == 'I')
{
if (!global.params.useDeprecated && *p == 'I')
if (*p == 'I')
error("'I' suffix is deprecated, use 'i' instead");
p++;
switch (result)
@@ -2427,6 +2430,7 @@ done:
case TOKfloat80v:
result = TOKimaginary80v;
break;
default: break;
}
}
#if _WIN32 && __DMC__
@@ -2839,8 +2843,8 @@ static Keyword keywords[] =
{ "uint", TOKuns32 },
{ "long", TOKint64 },
{ "ulong", TOKuns64 },
{ "cent", TOKcent, },
{ "ucent", TOKucent, },
{ "cent", TOKint128, },
{ "ucent", TOKuns128, },
{ "float", TOKfloat32 },
{ "double", TOKfloat64 },
{ "real", TOKfloat80 },
@@ -2943,7 +2947,7 @@ static Keyword keywords[] =
int Token::isKeyword()
{
for (unsigned u = 0; u < sizeof(keywords) / sizeof(keywords[0]); u++)
for (size_t u = 0; u < sizeof(keywords) / sizeof(keywords[0]); u++)
{
if (keywords[u].value == value)
return 1;
@@ -2953,7 +2957,7 @@ int Token::isKeyword()
void Lexer::initKeywords()
{
unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]);
size_t nkeywords = sizeof(keywords) / sizeof(keywords[0]);
stringtable.init(6151);
@@ -2962,7 +2966,7 @@ void Lexer::initKeywords()
cmtable_init();
for (unsigned u = 0; u < nkeywords; u++)
for (size_t u = 0; u < nkeywords; u++)
{
//printf("keyword[%d] = '%s'\n",u, keywords[u].name);
const char *s = keywords[u].name;
+8 -4
View File
@@ -120,11 +120,11 @@ enum TOK
TOKint16, TOKuns16,
TOKint32, TOKuns32,
TOKint64, TOKuns64,
TOKint128, TOKuns128,
TOKfloat32, TOKfloat64, TOKfloat80,
TOKimaginary32, TOKimaginary64, TOKimaginary80,
TOKcomplex32, TOKcomplex64, TOKcomplex80,
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKcent, TOKucent,
// 152
// Aggregates
@@ -191,6 +191,7 @@ enum TOK
case TOKint16: case TOKuns16: \
case TOKint32: case TOKuns32: \
case TOKint64: case TOKuns64: \
case TOKint128: case TOKuns128: \
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
@@ -206,6 +207,8 @@ enum TOK
case TOKuns32: t = Type::tuns32; goto LabelX; \
case TOKint64: t = Type::tint64; goto LabelX; \
case TOKuns64: t = Type::tuns64; goto LabelX; \
case TOKint128: t = Type::tint128; goto LabelX; \
case TOKuns128: t = Type::tuns128; goto LabelX; \
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
@@ -283,7 +286,7 @@ struct Lexer
int commentToken; // !=0 means comments are TOKcomment's
Lexer(Module *mod,
unsigned char *base, unsigned begoffset, unsigned endoffset,
unsigned char *base, size_t begoffset, size_t endoffset,
int doDocComment, int commentToken);
static void initKeywords();
@@ -310,8 +313,9 @@ struct Lexer
unsigned wchar(unsigned u);
TOK number(Token *t);
TOK inreal(Token *t);
void error(const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void error(const char *format, ...);
void error(Loc loc, const char *format, ...);
void deprecation(const char *format, ...);
void poundLine();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
+2
View File
@@ -26,5 +26,7 @@ class Library
virtual void write() = 0;
};
Library *LibMSCoff_factory();
#endif /* DMD_LIB_H */
+21 -20
View File
@@ -21,8 +21,9 @@
#include "macro.h"
#define isidstart(c) (isalpha(c) || (c) == '_')
#define isidchar(c) (isalnum(c) || (c) == '_')
int isIdStart(unsigned char *p);
int isIdTail(unsigned char *p);
int utfStride(unsigned char *p);
unsigned char *memdup(unsigned char *p, size_t len)
{
@@ -97,7 +98,7 @@ Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsign
* -1: get 2nd through end
*/
unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsigned *pmarglen, int n)
size_t extractArgN(unsigned char *p, size_t end, unsigned char **pmarg, size_t *pmarglen, int n)
{
/* Scan forward for matching right parenthesis.
* Nest parentheses.
@@ -114,7 +115,7 @@ unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsi
unsigned inexp = 0;
unsigned argn = 0;
unsigned v = 0;
size_t v = 0;
Largstart:
#if 1
@@ -236,8 +237,8 @@ unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsi
* Only look at the text in buf from start to end.
*/
void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
unsigned char *arg, unsigned arglen)
void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
unsigned char *arg, size_t arglen)
{
#if 0
printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg);
@@ -249,14 +250,14 @@ void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
return;
nest++;
unsigned end = *pend;
size_t end = *pend;
assert(start <= end);
assert(end <= buf->offset);
/* First pass - replace $0
*/
arg = memdup(arg, arglen);
for (unsigned u = start; u + 1 < end; )
for (size_t u = start; u + 1 < end; )
{
unsigned char *p = buf->data; // buf->data is not loop invariant
@@ -276,7 +277,7 @@ void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
int n = (c == '+') ? -1 : c - '0';
unsigned char *marg;
unsigned marglen;
size_t marglen;
extractArgN(arg, arglen, &marg, &marglen, n);
if (marglen == 0)
{ // Just remove macro invocation
@@ -293,7 +294,7 @@ void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
end += marglen - 2;
// Scan replaced text for further expansion
unsigned mend = u + marglen;
size_t mend = u + marglen;
expand(buf, u, &mend, NULL, 0);
end += mend - (u + marglen);
u = mend;
@@ -309,7 +310,7 @@ void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
end += -2 + 2 + marglen + 2;
// Scan replaced text for further expansion
unsigned mend = u + 2 + marglen;
size_t mend = u + 2 + marglen;
expand(buf, u + 2, &mend, NULL, 0);
end += mend - (u + 2 + marglen);
u = mend;
@@ -324,30 +325,30 @@ void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
/* Second pass - replace other macros
*/
for (unsigned u = start; u + 4 < end; )
for (size_t u = start; u + 4 < end; )
{
unsigned char *p = buf->data; // buf->data is not loop invariant
/* A valid start of macro expansion is $(c, where c is
* an id start character, and not $$(c.
*/
if (p[u] == '$' && p[u + 1] == '(' && isidstart(p[u + 2]))
if (p[u] == '$' && p[u + 1] == '(' && isIdStart(p+u+2))
{
//printf("\tfound macro start '%c'\n", p[u + 2]);
unsigned char *name = p + u + 2;
unsigned namelen = 0;
size_t namelen = 0;
unsigned char *marg;
unsigned marglen;
size_t marglen;
unsigned v;
size_t v;
/* Scan forward to find end of macro name and
* beginning of macro argument (marg).
*/
for (v = u + 2; v < end; v++)
for (v = u + 2; v < end; v+=utfStride(p+v))
{ unsigned char c = p[v];
if (!isidchar(c))
if (!isIdTail(p+v))
{ // We've gone past the end of the macro name.
namelen = v - (u + 2);
break;
@@ -402,7 +403,7 @@ void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
// Scan replaced text for further expansion
m->inuse++;
unsigned mend = v + 1 + 2+m->textlen+2;
size_t mend = v + 1 + 2+m->textlen+2;
expand(buf, v + 1, &mend, marg, marglen);
end += mend - (v + 1 + 2+m->textlen+2);
m->inuse--;
@@ -417,7 +418,7 @@ void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend,
// Scan replaced text for further expansion
m->inuse++;
unsigned mend = v + 1 + m->textlen;
size_t mend = v + 1 + m->textlen;
expand(buf, v + 1, &mend, marg, marglen);
end += mend - (v + 1 + m->textlen);
m->inuse--;
+2 -2
View File
@@ -38,8 +38,8 @@ struct Macro
public:
static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
void expand(OutBuffer *buf, unsigned start, unsigned *pend,
unsigned char *arg, unsigned arglen);
void expand(OutBuffer *buf, size_t start, size_t *pend,
unsigned char *arg, size_t arglen);
};
#endif
+2 -2
View File
@@ -51,10 +51,10 @@ char *mangle(Declaration *sthis)
else
{
id = s->ident->toChars();
int len = strlen(id);
size_t len = strlen(id);
char tmp[sizeof(len) * 3 + 1];
buf.prependstring(id);
sprintf(tmp, "%d", len);
sprintf(tmp, "%d", (int)len);
buf.prependstring(tmp);
}
}
+137 -75
View File
@@ -17,7 +17,7 @@
#include <string>
#include <cstdarg>
#if POSIX
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include <errno.h>
#endif
@@ -45,9 +45,9 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
#endif
#if !IN_LLVM
int response_expand(int *pargc, char ***pargv);
int response_expand(size_t *pargc, char ***pargv);
void browse(const char *url);
void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
void getenv_setargv(const char *envvar, size_t *pargc, char** *pargv);
void obj_start(char *srcfile);
void obj_end(Library *library, File *objfile);
@@ -55,6 +55,8 @@ void obj_end(Library *library, File *objfile);
void printCtfePerformanceStats();
static bool parse_arch(size_t argc, char** argv, bool is64bit);
Global global;
Global::Global()
@@ -99,7 +101,7 @@ Global::Global()
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.060";
version = "v2.061";
#if IN_LLVM
ldc_version = "trunk";
llvm_version = "LLVM "LDC_LLVM_VERSION_STRING;
@@ -195,33 +197,51 @@ void errorSupplemental(Loc loc, const char *format, ...)
va_end( ap );
}
void verror(Loc loc, const char *format, va_list ap, const char *p1, const char *p2)
void deprecation(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
vdeprecation(loc, format, ap);
va_end( ap );
}
// Just print, doesn't care about gagging
void verrorPrint(Loc loc, const char *header, const char *format, va_list ap,
const char *p1, const char *p2)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fputs(header, stdmsg);
if (p1)
fprintf(stdmsg, "%s ", p1);
if (p2)
fprintf(stdmsg, "%s ", p2);
#if _MSC_VER
// MS doesn't recognize %zu format
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stdmsg, "%s", tmp.toChars());
#else
vfprintf(stdmsg, format, ap);
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
// header is "Error: " by default (see mars.h)
void verror(Loc loc, const char *format, va_list ap,
const char *p1, const char *p2, const char *header)
{
if (!global.gag)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "Error: ");
if (p1)
fprintf(stdmsg, "%s ", p1);
if (p2)
fprintf(stdmsg, "%s ", p2);
#if _MSC_VER
// MS doesn't recognize %zu format
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stdmsg, "%s", tmp.toChars());
#else
vfprintf(stdmsg, format, ap);
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
verrorPrint(loc, header, format, ap, p1, p2);
if (global.errors >= 20) // moderate blizzard of cascading messages
fatal();
fatal();
//halt();
}
else
@@ -235,48 +255,30 @@ void verror(Loc loc, const char *format, va_list ap, const char *p1, const char
void verrorSupplemental(Loc loc, const char *format, va_list ap)
{
if (!global.gag)
{
fprintf(stdmsg, "%s: ", loc.toChars());
#if _MSC_VER
// MS doesn't recognize %zu format
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stdmsg, "%s", tmp.toChars());
#else
vfprintf(stdmsg, format, ap);
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
verrorPrint(loc, " ", format, ap);
}
void vwarning(Loc loc, const char *format, va_list ap)
{
if (global.params.warnings && !global.gag)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "Warning: ");
#if _MSC_VER
// MS doesn't recognize %zu format
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stdmsg, "%s", tmp.toChars());
#else
vfprintf(stdmsg, format, ap);
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
verrorPrint(loc, "Warning: ", format, ap);
//halt();
if (global.params.warnings == 1)
global.warnings++; // warnings don't count if gagged
}
}
void vdeprecation(Loc loc, const char *format, va_list ap,
const char *p1, const char *p2)
{
static const char *header = "Deprecation: ";
if (global.params.useDeprecated == 0)
verror(loc, format, ap, p1, p2, header);
else if (global.params.useDeprecated == 2 && !global.gag)
verrorPrint(loc, header, format, ap, p1, p2);
}
/***************************************
* Call this after printing out fatal error messages to clean up and exit
* the compiler.
@@ -315,8 +317,8 @@ void usage()
#else
const char fpic[] = "";
#endif
printf("DMD%s D Compiler %s\n%s %s\n",
sizeof(size_t) == 4 ? "32" : "64",
printf("DMD%d D Compiler %s\n%s %s\n",
sizeof(size_t) * 8,
global.version, global.copyright, global.written);
printf("\
Documentation: http://www.dlang.org/index.html\n\
@@ -330,7 +332,9 @@ Usage:\n\
-D generate documentation\n\
-Dddocdir write documentation file to docdir directory\n\
-Dffilename write documentation file to filename\n\
-d allow deprecated features\n\
-d silently allow deprecated features\n\
-dw show use of deprecated features as warnings (default)\n\
-de show use of deprecated features as errors (halt compilation)\n\
-debug compile in debug code\n\
-debug=level compile in debug code <= level\n\
-debug=ident compile in debug code identified by ident\n\
@@ -357,7 +361,6 @@ Usage:\n\
" -man open web browser on manual page\n\
-map generate linker .map file\n\
-noboundscheck turns off array bounds checking for all functions\n\
-nofloat do not emit reference to floating point\n\
-O optimize\n\
-o- do not write object file\n\
-odobjdir write object & library files to directory objdir\n\
@@ -393,7 +396,7 @@ extern "C"
}
#endif
int tryMain(int argc, char *argv[])
int tryMain(size_t argc, char *argv[])
{
mem.init(); // initialize storage allocator
mem.setStackBottom(&argv);
@@ -405,10 +408,10 @@ int tryMain(int argc, char *argv[])
Strings libmodules;
char *p;
Module *m;
int status = EXIT_SUCCESS;
int argcstart = argc;
size_t argcstart = argc;
int setdebuglib = 0;
char noboundscheck = 0;
int setdefaultlib = 0;
const char *inifilename = NULL;
#ifdef DEBUG
@@ -448,6 +451,7 @@ int tryMain(int argc, char *argv[])
global.params.obj = 1;
global.params.Dversion = 2;
global.params.quiet = 1;
global.params.useDeprecated = 2;
global.params.linkswitches = new Strings();
global.params.libfiles = new Strings();
@@ -512,12 +516,24 @@ int tryMain(int argc, char *argv[])
VersionCondition::addPredefinedGlobalIdent("all");
#if _WIN32
inifilename = inifile(argv[0], "sc.ini");
#elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
inifilename = inifile(argv[0], "dmd.conf");
inifilename = inifile(argv[0], "sc.ini", "Environment");
#elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
inifilename = inifile(argv[0], "dmd.conf", "Environment");
#else
#error "fix this"
#endif
size_t dflags_argc = 0;
char** dflags_argv = NULL;
getenv_setargv("DFLAGS", &dflags_argc, &dflags_argv);
bool is64bit = global.params.is64bit; // use default
is64bit = parse_arch(argc, argv, is64bit);
is64bit = parse_arch(dflags_argc, dflags_argv, is64bit);
global.params.is64bit = is64bit;
inifile(argv[0], inifilename, is64bit ? "Environment64" : "Environment32");
getenv_setargv("DFLAGS", &argc, &argv);
#if 0
@@ -532,8 +548,12 @@ int tryMain(int argc, char *argv[])
p = argv[i];
if (*p == '-')
{
if (strcmp(p + 1, "d") == 0)
if (strcmp(p + 1, "de") == 0)
global.params.useDeprecated = 0;
else if (strcmp(p + 1, "d") == 0)
global.params.useDeprecated = 1;
else if (strcmp(p + 1, "dw") == 0)
global.params.useDeprecated = 2;
else if (strcmp(p + 1, "c") == 0)
global.params.link = 0;
else if (strcmp(p + 1, "cov") == 0)
@@ -560,7 +580,7 @@ int tryMain(int argc, char *argv[])
else if (strcmp(p + 1, "gs") == 0)
global.params.alwaysframe = 1;
else if (strcmp(p + 1, "gt") == 0)
{ error(0, "use -profile instead of -gt\n");
{ error(0, "use -profile instead of -gt");
global.params.trace = 1;
}
else if (strcmp(p + 1, "m32") == 0)
@@ -700,6 +720,8 @@ int tryMain(int argc, char *argv[])
global.params.quiet = 1;
else if (strcmp(p + 1, "release") == 0)
global.params.release = 1;
else if (strcmp(p + 1, "betterC") == 0)
global.params.betterC = 1;
#if DMDV2
else if (strcmp(p + 1, "noboundscheck") == 0)
noboundscheck = 1;
@@ -745,7 +767,7 @@ int tryMain(int argc, char *argv[])
else
global.params.debuglevel = 1;
}
else if (memcmp(p + 1, "version", 5) == 0)
else if (memcmp(p + 1, "version", 7) == 0)
{
// Parse:
// -version=number
@@ -791,6 +813,7 @@ int tryMain(int argc, char *argv[])
}
else if (memcmp(p + 1, "defaultlib=", 11) == 0)
{
setdefaultlib = 1;
global.params.defaultlibname = p + 1 + 11;
}
else if (memcmp(p + 1, "debuglib=", 9) == 0)
@@ -883,6 +906,11 @@ int tryMain(int argc, char *argv[])
files.push(p);
}
}
if(global.params.is64bit != is64bit)
error(0, "the architecture must not be changed in the %s section of %s",
is64bit ? "Environment64" : "Environment32", inifilename);
if (global.errors)
{
fatal();
@@ -901,7 +929,7 @@ int tryMain(int argc, char *argv[])
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
if (global.params.lib && global.params.dll)
error(0, "cannot mix -lib and -shared\n");
error(0, "cannot mix -lib and -shared");
#endif
if (global.params.release)
@@ -983,6 +1011,11 @@ int tryMain(int argc, char *argv[])
VersionCondition::addPredefinedGlobalIdent("D_SIMD");
#if TARGET_WINDOS
VersionCondition::addPredefinedGlobalIdent("Win64");
if (!setdefaultlib)
{ global.params.defaultlibname = "phobos64";
if (!setdebuglib)
global.params.debuglibname = global.params.defaultlibname;
}
#endif
}
else
@@ -1006,8 +1039,14 @@ int tryMain(int argc, char *argv[])
#if DMDV2
if (global.params.useUnitTests)
VersionCondition::addPredefinedGlobalIdent("unittest");
if (global.params.useAssert)
VersionCondition::addPredefinedGlobalIdent("assert");
if (noboundscheck)
VersionCondition::addPredefinedGlobalIdent("D_NoBoundsChecks");
#endif
VersionCondition::addPredefinedGlobalIdent("D_HardFloat");
// Initialization
Type::init();
Id::initialize();
@@ -1156,7 +1195,7 @@ int tryMain(int argc, char *argv[])
}
}
else
{ error(0, "unrecognized file extension %s\n", ext);
{ error(0, "unrecognized file extension %s", ext);
fatal();
}
}
@@ -1283,7 +1322,7 @@ int tryMain(int argc, char *argv[])
m->importAll(0);
}
if (global.errors)
fatal();
fatal();
backend_init();
@@ -1445,6 +1484,7 @@ int tryMain(int argc, char *argv[])
if (global.errors)
fatal();
int status = EXIT_SUCCESS;
if (!global.params.objfiles->dim)
{
if (global.params.link)
@@ -1505,7 +1545,7 @@ int main(int argc, char *argv[])
* The string is separated into arguments, processing \ and ".
*/
void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
void getenv_setargv(const char *envvar, size_t *pargc, char** *pargv)
{
char *p;
@@ -1519,7 +1559,7 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
env = mem.strdup(env); // create our own writable copy
int argc = *pargc;
size_t argc = *pargc;
Strings *argv = new Strings();
argv->setDim(argc);
@@ -1623,6 +1663,28 @@ Ldone:
*pargv = argv->tdata();
}
/***********************************
* Parse command line arguments for -m32 or -m64
* to detect the desired architecture.
*/
static bool parse_arch(size_t argc, char** argv, bool is64bit)
{
for (size_t i = 0; i < argc; ++i)
{ char* p = argv[i];
if (p[0] == '-')
{
if (strcmp(p + 1, "m32") == 0)
is64bit = 0;
else if (strcmp(p + 1, "m64") == 0)
is64bit = 1;
else if (strcmp(p + 1, "run") == 0)
break;
}
}
return is64bit;
}
#if WINDOWS_SEH
long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep)
+35 -14
View File
@@ -39,7 +39,7 @@ Macros defined by the compiler, not the code:
__APPLE__ Mac OSX
__FreeBSD__ FreeBSD
__OpenBSD__ OpenBSD
__sun&&__SVR4 Solaris, OpenSolaris (yes, both macros are necessary)
__sun Solaris, OpenSolaris, SunOS, OpenIndiana, etc
For the target systems, there are the target operating system and
the target object file format:
@@ -203,25 +203,39 @@ struct Param
ARCH cpu; // target CPU
bool isLE; // generate little endian code
bool is64bit; // generate 64 bit code
#if !IN_LLVM
#if IN_LLVM
OS os;
#else
char isLinux; // generate code for linux
char isOSX; // generate code for Mac OSX
char isWindows; // generate code for Windows
char isFreeBSD; // generate code for FreeBSD
char isOPenBSD; // generate code for OpenBSD
char isSolaris; // generate code for Solaris
#else
OS os;
char scheduler; // which scheduler to use
#endif
bool useDeprecated; // allow use of deprecated features
ubyte useDeprecated; // 0: don't allow use of deprecated features
// 1: silently allow use of deprecated features
// 2: warn about the use of deprecated features
bool useAssert; // generate runtime code for assert()'s
bool useInvariants; // generate class invariant checks
bool useIn; // generate precondition checks
bool useOut; // generate postcondition checks
bool useArrayBounds;// generate array bounds checks
bool useSwitchError;// check for switches without a default
#if IN_LLVM
bool useArrayBounds;
#else
char useArrayBounds; // 0: no array bounds checks
// 1: array bounds checks for safe functions only
// 2: array bounds checks for all functions
#endif
bool noboundscheck; // no array bounds checking at all
bool useSwitchError; // check for switches without a default
bool useUnitTests; // generate unittest code
bool useInline; // inline expand functions
#if !IN_LLVM
char release; // build release version
char preservePaths; // !=0 means don't strip path from source file
#endif
ubyte warnings; // 0: enable warnings
// 1: warnings as errors
// 2: informational warnings (no errors)
@@ -230,9 +244,12 @@ struct Param
char cov; // generate code coverage data
char nofloat; // code should not pull in floating point support
#endif
ubyte Dversion; // D version number
ubyte Dversion; // D version number
bool ignoreUnsupportedPragmas; // rather than error on them
bool enforcePropertySyntax;
#if !IN_LLVM
char betterC; // be a "better C" compiler; no dependency on D runtime
#endif
char *argv0; // program name
Strings *imppath; // array of char*'s of where to look for import modules
@@ -493,6 +510,7 @@ enum DYNCAST
DYNCAST_TYPE,
DYNCAST_IDENTIFIER,
DYNCAST_TUPLE,
DYNCAST_PARAMETER,
};
enum MATCH
@@ -508,12 +526,15 @@ enum MATCH
typedef uint64_t StorageClass;
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(2);
void warning(Loc loc, const char *format, ...);
void deprecation(Loc loc, const char *format, ...);
void error(Loc loc, const char *format, ...);
void errorSupplemental(Loc loc, const char *format, ...);
void verror(Loc loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL);
void verror(Loc loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL, const char *header = "Error: ");
void vwarning(Loc loc, const char *format, va_list);
void verrorSupplemental(Loc loc, const char *format, va_list);
void verrorSupplemental(Loc loc, const char *format, va_list ap);
void verrorPrint(Loc loc, const char *header, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL);
void vdeprecation(Loc loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL);
#if defined(__GNUC__) || defined(__clang__)
__attribute__((noreturn))
@@ -527,7 +548,7 @@ void error(const char *format, ...) IS_PRINTF(1);
int runLINK();
void deleteExeFile();
int runProgram();
const char *inifile(const char *argv0, const char *inifile);
const char *inifile(const char *argv0, const char *inifile, const char* envsectionname);
#endif
void halt();
#if !IN_LLVM
@@ -543,7 +564,7 @@ void util_progress();
#if !IN_LLVM
struct Dsymbol;
struct Library;
class Library;
struct File;
void obj_start(char *srcfile);
void obj_end(Library *library, File *objfile);
+23 -9
View File
@@ -12,7 +12,7 @@
#include <stdlib.h>
#include <assert.h>
#if (defined (__SVR4) && defined (__sun))
#if defined (__sun)
#include <alloca.h>
#endif
@@ -179,7 +179,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
#endif
if (global.params.objname)
objfilename = new FileName(argobj, 0);
objfilename = new FileName(argobj);
else
objfilename = FileName::forceExt(argobj, global.obj_ext);
@@ -281,7 +281,7 @@ void Module::setDocfile()
argdoc = FileName::combine(global.params.docdir, argdoc);
}
if (global.params.docname)
docfilename = new FileName(argdoc, 0);
docfilename = new FileName(argdoc);
else
docfilename = FileName::forceExt(argdoc, global.doc_ext);
@@ -309,7 +309,7 @@ void Module::setHdrfile()
arghdr = FileName::combine(global.params.hdrdir, arghdr);
}
if (global.params.hdrname)
hdrfilename = new FileName(arghdr, 0);
hdrfilename = new FileName(arghdr);
else
hdrfilename = FileName::forceExt(arghdr, global.hdr_ext);
@@ -515,7 +515,17 @@ bool Module::read(Loc loc)
{
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
if (srcfile->read())
{ error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
{
if (!strcmp(srcfile->toChars(), "object.d"))
{
::error(loc, "cannot find source code for runtime library file 'object.d'");
errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
}
else
{
error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
}
if (!global.gag)
{ /* Print path
*/
@@ -582,7 +592,7 @@ void Module::parse()
//printf("Module::parse(srcname = '%s')\n", srcname);
unsigned char *buf = srcfile->buffer;
unsigned buflen = srcfile->len;
size_t buflen = srcfile->len;
if (buflen >= 2)
{
@@ -1165,7 +1175,7 @@ void Module::runDeferredSemantic()
static int nested;
if (nested)
return;
//if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
//if (deferred.dim) printf("+Module::runDeferredSemantic(), len = %d\n", deferred.dim);
nested++;
size_t len;
@@ -1177,6 +1187,7 @@ void Module::runDeferredSemantic()
break;
Dsymbol **todo;
Dsymbol **todoalloc = NULL;
Dsymbol *tmp;
if (len == 1)
{
@@ -1184,8 +1195,9 @@ void Module::runDeferredSemantic()
}
else
{
todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *));
todo = (Dsymbol **)malloc(len * sizeof(Dsymbol *));
assert(todo);
todoalloc = todo;
}
memcpy(todo, deferred.tdata(), len * sizeof(Dsymbol *));
deferred.setDim(0);
@@ -1198,9 +1210,11 @@ void Module::runDeferredSemantic()
//printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
}
//printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
if (todoalloc)
free(todoalloc);
} while (deferred.dim < len || dprogress); // while making progress
nested--;
//printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
//printf("-Module::runDeferredSemantic(), len = %d\n", deferred.dim);
}
/************************************
+2 -2
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -24,7 +24,7 @@ struct ModuleDeclaration;
struct Macro;
struct Escape;
struct VarDeclaration;
struct Library;
class Library;
// Back end
#if IN_LLVM
+415 -159
View File
File diff suppressed because it is too large Load Diff
+22 -5
View File
@@ -108,6 +108,8 @@ enum ENUMTY
Treturn,
Tnull,
Tvector,
Tint128,
Tuns128,
TMAX
};
typedef unsigned char TY; // ENUMTY
@@ -163,6 +165,8 @@ struct Type : Object
#define tuns32 basic[Tuns32]
#define tint64 basic[Tint64]
#define tuns64 basic[Tuns64]
#define tint128 basic[Tint128]
#define tuns128 basic[Tuns128]
#define tfloat32 basic[Tfloat32]
#define tfloat64 basic[Tfloat64]
#define tfloat80 basic[Tfloat80]
@@ -271,7 +275,7 @@ struct Type : Object
virtual int isunsigned();
virtual int isscope();
virtual int isString();
virtual int isAssignable();
virtual int isAssignable(int blit = 0);
virtual int checkBoolean(); // if can be converted to boolean value
virtual void checkDeprecated(Loc loc, Scope *sc);
int isConst() { return mod & MODconst; }
@@ -342,6 +346,7 @@ struct Type : Object
virtual Type *nextOf();
uinteger_t sizemask();
virtual int needsDestruction();
virtual bool needsNested();
static void error(Loc loc, const char *format, ...) IS_PRINTF(2);
@@ -466,6 +471,10 @@ struct TypeVector : Type
int isZeroInit(Loc loc);
TypeInfoDeclaration *getTypeInfoDeclaration();
TypeTuple *toArgTypes();
#if IN_DMD
type *toCtype();
#endif
};
struct TypeArray : TypeNext
@@ -505,6 +514,7 @@ struct TypeSArray : TypeArray
Expression *toExpression();
int hasPointers();
int needsDestruction();
bool needsNested();
TypeTuple *toArgTypes();
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
@@ -671,6 +681,7 @@ struct TypeFunction : TypeNext
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
bool hasMutableIndirectionParams();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
@@ -686,7 +697,7 @@ struct TypeFunction : TypeNext
bool parameterEscapes(Parameter *p);
Type *addStorageClass(StorageClass stc);
int callMatch(Expression *ethis, Expressions *toargs, int flag = 0);
MATCH callMatch(Expression *ethis, Expressions *toargs, int flag = 0);
#if IN_DMD
type *toCtype();
#endif
@@ -751,6 +762,7 @@ struct TypeQualified : Type
struct TypeIdentifier : TypeQualified
{
Identifier *ident;
Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution
TypeIdentifier(Loc loc, Identifier *ident);
Type *syntaxCopy();
@@ -824,9 +836,10 @@ struct TypeStruct : Type
Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);
int isZeroInit(Loc loc);
int isAssignable();
int isAssignable(int blit = 0);
int checkBoolean();
int needsDestruction();
bool needsNested();
#if IN_DMD
dt_t **toDt(dt_t **pdt);
#endif
@@ -875,8 +888,9 @@ struct TypeEnum : Type
int isscalar();
int isunsigned();
int checkBoolean();
int isAssignable();
int isAssignable(int blit = 0);
int needsDestruction();
bool needsNested();
MATCH implicitConvTo(Type *to);
MATCH constConv(Type *to);
Type *toBasetype();
@@ -919,8 +933,9 @@ struct TypeTypedef : Type
int isscalar();
int isunsigned();
int checkBoolean();
int isAssignable();
int isAssignable(int blit = 0);
int needsDestruction();
bool needsNested();
Type *toBasetype();
MATCH implicitConvTo(Type *to);
MATCH constConv(Type *to);
@@ -1050,6 +1065,7 @@ struct Parameter : Object
Parameter *syntaxCopy();
Type *isLazyArray();
void toDecoBuffer(OutBuffer *buf, bool mangle);
int dyncast() { return DYNCAST_PARAMETER; } // kludge for template.isType()
static Parameters *arraySyntaxCopy(Parameters *args);
static char *argsTypesToChars(Parameters *args, int varargs);
static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs);
@@ -1076,5 +1092,6 @@ void MODtoBuffer(OutBuffer *buf, unsigned char mod);
int MODimplicitConv(unsigned char modfrom, unsigned char modto);
int MODmethodConv(unsigned char modfrom, unsigned char modto);
int MODmerge(unsigned char mod1, unsigned char mod2);
void identifierToDocBuffer(Identifier* ident, OutBuffer *buf, HdrGenState *hgs);
#endif /* DMD_MTYPE_H */
+34 -34
View File
@@ -237,6 +237,7 @@ Expression *UnaExp::op_overload(Scope *sc)
Dsymbol *fd = search_function(ad, Id::opIndexUnary);
if (fd)
{
ae = resolveOpDollar(sc, ae);
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi);
e = new CallExp(loc, e, ae->arguments);
@@ -274,12 +275,13 @@ Expression *UnaExp::op_overload(Scope *sc)
Dsymbol *fd = search_function(ad, Id::opSliceUnary);
if (fd)
{
se = resolveOpDollar(sc, se);
Expressions *a = new Expressions();
assert(!se->lwr || se->upr);
if (se->lwr)
{ a->push(se->lwr);
a->push(se->upr);
}
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, targsi);
e = new CallExp(loc, e, a);
@@ -376,35 +378,12 @@ Expression *ArrayExp::op_overload(Scope *sc)
Dsymbol *fd = search_function(ad, opId());
if (fd)
{
for (size_t i = 0; i < arguments->dim; i++)
{ Expression *x = (*arguments)[i];
// Create scope for '$' variable for this dimension
ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, this);
sym->loc = loc;
sym->parent = sc->scopesym;
sc = sc->push(sym);
lengthVar = NULL; // Create it only if required
currentDimension = i; // Dimension for $, if required
x = x->semantic(sc);
x = resolveProperties(sc, x);
if (!x->type)
error("%s has no value", x->toChars());
if (lengthVar)
{ // If $ was used, declare it now
Expression *av = new DeclarationExp(loc, lengthVar);
x = new CommaExp(0, av, x);
x->semantic(sc);
}
(*arguments)[i] = x;
sc = sc->pop();
}
/* Rewrite op e1[arguments] as:
* e1.opIndex(arguments)
*/
Expression *e = new DotIdExp(loc, e1, fd->ident);
e = new CallExp(loc, e, arguments);
ArrayExp *ae = resolveOpDollar(sc, this);
Expression *e = new DotIdExp(loc, ae->e1, fd->ident);
e = new CallExp(loc, e, ae->arguments);
e = e->semantic(sc);
return e;
}
@@ -810,7 +789,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, NULL, &args2);
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
}
}
@@ -826,7 +805,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
}
else
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, NULL, &args1);
templateResolve(&m, td, sc, loc, targsi, e2, &args1);
}
}
@@ -988,10 +967,9 @@ Expression *BinAssignExp::op_overload(Scope *sc)
Dsymbol *fd = search_function(ad, Id::opIndexOpAssign);
if (fd)
{
Expressions *a = new Expressions();
a->push(e2);
for (size_t i = 0; i < ae->arguments->dim; i++)
a->push((*ae->arguments)[i]);
ae = resolveOpDollar(sc, ae);
Expressions *a = (Expressions *)ae->arguments->copy();
a->insert(0, e2);
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi);
@@ -1030,8 +1008,10 @@ Expression *BinAssignExp::op_overload(Scope *sc)
Dsymbol *fd = search_function(ad, Id::opSliceOpAssign);
if (fd)
{
se = resolveOpDollar(sc, se);
Expressions *a = new Expressions();
a->push(e2);
assert(!se->lwr || se->upr);
if (se->lwr)
{ a->push(se->lwr);
a->push(se->upr);
@@ -1345,7 +1325,10 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
for (size_t u = 0; u < arguments->dim; u++)
{ Parameter *arg = (*arguments)[u];
if (arg->type)
{
arg->type = arg->type->semantic(loc, sc);
arg->type = arg->type->addStorageClass(arg->storageClass);
}
}
Expression *ethis;
@@ -1396,11 +1379,17 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
if (arguments->dim == 2)
{
if (!arg->type)
{
arg->type = Type::tsize_t; // key type
arg->type = arg->type->addStorageClass(arg->storageClass);
}
arg = (*arguments)[1];
}
if (!arg->type && tab->ty != Ttuple)
{
arg->type = tab->nextOf(); // value type
arg->type = arg->type->addStorageClass(arg->storageClass);
}
break;
case Taarray:
@@ -1409,11 +1398,17 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
if (arguments->dim == 2)
{
if (!arg->type)
{
arg->type = taa->index; // key type
arg->type = arg->type->addStorageClass(arg->storageClass);
}
arg = (*arguments)[1];
}
if (!arg->type)
{
arg->type = taa->next; // value type
arg->type = arg->type->addStorageClass(arg->storageClass);
}
break;
}
@@ -1440,7 +1435,10 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
// Resolve inout qualifier of front type
arg->type = fd->type->nextOf();
if (arg->type)
{
arg->type = arg->type->substWildTo(tab->mod);
arg->type = arg->type->addStorageClass(arg->storageClass);
}
}
else if (s && s->isTemplateDeclaration())
;
@@ -1560,7 +1558,10 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flag
goto Lnomatch;
}
else if (!flags)
{
arg->type = param->type;
arg->type = arg->type->addStorageClass(arg->storageClass);
}
}
Lmatch:
return 1;
@@ -1626,4 +1627,3 @@ static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc lo
m->count = 1;
}
}
+95 -70
View File
@@ -180,6 +180,7 @@ Expression *fromConstInitializer(int result, Expression *e1)
!(v->storage_class & STCtemplateparameter))
{
e1->error("variable %s cannot be read at compile time", v->toChars());
e->type = Type::terror;
}
}
}
@@ -187,18 +188,18 @@ Expression *fromConstInitializer(int result, Expression *e1)
}
Expression *Expression::optimize(int result)
Expression *Expression::optimize(int result, bool keepLvalue)
{
//printf("Expression::optimize(result = x%x) %s\n", result, toChars());
return this;
}
Expression *VarExp::optimize(int result)
Expression *VarExp::optimize(int result, bool keepLvalue)
{
return fromConstInitializer(result, this);
return keepLvalue ? this : fromConstInitializer(result, this);
}
Expression *TupleExp::optimize(int result)
Expression *TupleExp::optimize(int result, bool keepLvalue)
{
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (*exps)[i];
@@ -209,7 +210,7 @@ Expression *TupleExp::optimize(int result)
return this;
}
Expression *ArrayLiteralExp::optimize(int result)
Expression *ArrayLiteralExp::optimize(int result, bool keepLvalue)
{
if (elements)
{
@@ -223,7 +224,7 @@ Expression *ArrayLiteralExp::optimize(int result)
return this;
}
Expression *AssocArrayLiteralExp::optimize(int result)
Expression *AssocArrayLiteralExp::optimize(int result, bool keepLvalue)
{
assert(keys->dim == values->dim);
for (size_t i = 0; i < keys->dim; i++)
@@ -239,7 +240,7 @@ Expression *AssocArrayLiteralExp::optimize(int result)
return this;
}
Expression *StructLiteralExp::optimize(int result)
Expression *StructLiteralExp::optimize(int result, bool keepLvalue)
{
if (elements)
{
@@ -254,19 +255,19 @@ Expression *StructLiteralExp::optimize(int result)
return this;
}
Expression *TypeExp::optimize(int result)
Expression *TypeExp::optimize(int result, bool keepLvalue)
{
return this;
}
Expression *UnaExp::optimize(int result)
Expression *UnaExp::optimize(int result, bool keepLvalue)
{
//printf("UnaExp::optimize() %s\n", toChars());
e1 = e1->optimize(result);
return this;
}
Expression *NegExp::optimize(int result)
Expression *NegExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -279,7 +280,7 @@ Expression *NegExp::optimize(int result)
return e;
}
Expression *ComExp::optimize(int result)
Expression *ComExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -292,7 +293,7 @@ Expression *ComExp::optimize(int result)
return e;
}
Expression *NotExp::optimize(int result)
Expression *NotExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -305,7 +306,7 @@ Expression *NotExp::optimize(int result)
return e;
}
Expression *BoolExp::optimize(int result)
Expression *BoolExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -318,7 +319,7 @@ Expression *BoolExp::optimize(int result)
return e;
}
Expression *AddrExp::optimize(int result)
Expression *AddrExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
@@ -403,7 +404,7 @@ Expression *AddrExp::optimize(int result)
&& !ve->var->isImportedSymbol())
{
TypeSArray *ts = (TypeSArray *)ve->type;
dinteger_t dim = ts->dim->toInteger();
sinteger_t dim = ts->dim->toInteger();
if (index < 0 || index >= dim)
error("array index %lld is out of bounds [0..%lld]", index, dim);
e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
@@ -416,7 +417,7 @@ Expression *AddrExp::optimize(int result)
return this;
}
Expression *PtrExp::optimize(int result)
Expression *PtrExp::optimize(int result, bool keepLvalue)
{
//printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
e1 = e1->optimize(result);
@@ -435,6 +436,9 @@ Expression *PtrExp::optimize(int result)
}
return e;
}
if (keepLvalue)
return this;
// Constant fold *(&structliteral + offset)
if (e1->op == TOKadd)
{
@@ -458,10 +462,12 @@ Expression *PtrExp::optimize(int result)
return this;
}
Expression *DotVarExp::optimize(int result)
Expression *DotVarExp::optimize(int result, bool keepLvalue)
{
//printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
e1 = e1->optimize(result);
if (keepLvalue)
return this;
Expression *e = e1;
@@ -485,7 +491,7 @@ Expression *DotVarExp::optimize(int result)
return this;
}
Expression *NewExp::optimize(int result)
Expression *NewExp::optimize(int result, bool keepLvalue)
{
if (thisexp)
thisexp = thisexp->optimize(WANTvalue);
@@ -517,23 +523,37 @@ Expression *NewExp::optimize(int result)
return this;
}
Expression *CallExp::optimize(int result)
Expression *CallExp::optimize(int result, bool keepLvalue)
{
//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
Expression *e = this;
// Optimize parameters
// Optimize parameters with keeping lvalue-ness
if (arguments)
{
Type *t1 = e1->type->toBasetype();
if (t1->ty == Tdelegate) t1 = t1->nextOf();
assert(t1->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)t1;
size_t pdim = Parameter::dim(tf->parameters) - (tf->varargs == 2 ? 1 : 0);
for (size_t i = 0; i < arguments->dim; i++)
{ Expression *e = (*arguments)[i];
e = e->optimize(WANTvalue);
{
bool keepLvalue = false;
if (i < pdim)
{
Parameter *p = Parameter::getNth(tf->parameters, i);
keepLvalue = ((p->storageClass & (STCref | STCout)) != 0);
}
Expression *e = (*arguments)[i];
e = e->optimize(WANTvalue, keepLvalue);
(*arguments)[i] = e;
}
}
e1 = e1->optimize(result);
if (keepLvalue)
return this;
#if 1
if (result & WANTinterpret)
{
@@ -585,7 +605,7 @@ Expression *CallExp::optimize(int result)
}
Expression *CastExp::optimize(int result)
Expression *CastExp::optimize(int result, bool keepLvalue)
{
#if IN_LLVM
if (disableOptimization)
@@ -634,9 +654,8 @@ Expression *CastExp::optimize(int result)
if (e1->op == TOKstructliteral &&
e1->type->implicitConvTo(type) >= MATCHconst)
{
e1->type = type;
if (X) printf(" returning2 %s\n", e1->toChars());
return e1;
goto L1;
}
/* The first test here is to prevent infinite loops
@@ -646,9 +665,8 @@ Expression *CastExp::optimize(int result)
if (e1->op == TOKnull &&
(type->ty == Tpointer || type->ty == Tclass || type->ty == Tarray))
{
e1->type = type;
if (X) printf(" returning3 %s\n", e1->toChars());
return e1;
goto L1;
}
if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
@@ -662,18 +680,16 @@ Expression *CastExp::optimize(int result)
cdto = type->isClassHandle();
if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
{
e1->type = type;
if (X) printf(" returning4 %s\n", e1->toChars());
return e1;
goto L1;
}
}
// We can convert 'head const' to mutable
if (to->mutableOf()->constOf()->equals(e1->type->mutableOf()->constOf()))
{
e1->type = type;
if (X) printf(" returning5 %s\n", e1->toChars());
return e1;
goto L1;
}
Expression *e;
@@ -685,8 +701,7 @@ Expression *CastExp::optimize(int result)
if (type->size() == e1->type->size() &&
type->toBasetype()->ty != Tsarray)
{
e1->type = type;
return e1;
goto L1;
}
return this;
}
@@ -699,10 +714,14 @@ Expression *CastExp::optimize(int result)
e = this;
if (X) printf(" returning6 %s\n", e->toChars());
return e;
L1: // Returning e1 with changing its type
e = (e1old == e1 ? e1->copy() : e1);
e->type = type;
return e;
#undef X
}
Expression *BinExp::optimize(int result)
Expression *BinExp::optimize(int result, bool keepLvalue)
{
//printf("BinExp::optimize(result = %d) %s\n", result, toChars());
if (op != TOKconstruct && op != TOKblit) // don't replace const variable with its initializer
@@ -712,7 +731,7 @@ Expression *BinExp::optimize(int result)
{
if (e2->isConst() == 1)
{
dinteger_t i2 = e2->toInteger();
sinteger_t i2 = e2->toInteger();
d_uns64 sz = e1->type->size() * 8;
if (i2 < 0 || i2 >= sz)
{ error("shift assign by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
@@ -723,7 +742,7 @@ Expression *BinExp::optimize(int result)
return this;
}
Expression *AddExp::optimize(int result)
Expression *AddExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("AddExp::optimize(%s)\n", toChars());
@@ -740,7 +759,7 @@ Expression *AddExp::optimize(int result)
return e;
}
Expression *MinExp::optimize(int result)
Expression *MinExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -756,7 +775,7 @@ Expression *MinExp::optimize(int result)
return e;
}
Expression *MulExp::optimize(int result)
Expression *MulExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("MulExp::optimize(result = %d) %s\n", result, toChars());
@@ -771,7 +790,7 @@ Expression *MulExp::optimize(int result)
return e;
}
Expression *DivExp::optimize(int result)
Expression *DivExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("DivExp::optimize(%s)\n", toChars());
@@ -786,7 +805,7 @@ Expression *DivExp::optimize(int result)
return e;
}
Expression *ModExp::optimize(int result)
Expression *ModExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -807,7 +826,7 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E
e->e2 = e->e2->optimize(result);
if (e->e2->isConst() == 1)
{
dinteger_t i2 = e->e2->toInteger();
sinteger_t i2 = e->e2->toInteger();
d_uns64 sz = e->e1->type->size() * 8;
if (i2 < 0 || i2 >= sz)
{ e->error("shift by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
@@ -819,25 +838,25 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E
return ex;
}
Expression *ShlExp::optimize(int result)
Expression *ShlExp::optimize(int result, bool keepLvalue)
{
//printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
return shift_optimize(result, this, Shl);
}
Expression *ShrExp::optimize(int result)
Expression *ShrExp::optimize(int result, bool keepLvalue)
{
//printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
return shift_optimize(result, this, Shr);
}
Expression *UshrExp::optimize(int result)
Expression *UshrExp::optimize(int result, bool keepLvalue)
{
//printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
return shift_optimize(result, this, Ushr);
}
Expression *AndExp::optimize(int result)
Expression *AndExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -849,7 +868,7 @@ Expression *AndExp::optimize(int result)
return e;
}
Expression *OrExp::optimize(int result)
Expression *OrExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -861,7 +880,7 @@ Expression *OrExp::optimize(int result)
return e;
}
Expression *XorExp::optimize(int result)
Expression *XorExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -873,7 +892,7 @@ Expression *XorExp::optimize(int result)
return e;
}
Expression *PowExp::optimize(int result)
Expression *PowExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(result);
@@ -938,7 +957,7 @@ Expression *PowExp::optimize(int result)
return e;
}
Expression *CommaExp::optimize(int result)
Expression *CommaExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
@@ -956,7 +975,7 @@ Expression *CommaExp::optimize(int result)
}
e1 = e1->optimize(result & WANTinterpret);
e2 = e2->optimize(result);
e2 = e2->optimize(result, keepLvalue);
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->hasSideEffect())
{
e = e2;
@@ -969,7 +988,7 @@ Expression *CommaExp::optimize(int result)
return e;
}
Expression *ArrayLengthExp::optimize(int result)
Expression *ArrayLengthExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
@@ -982,24 +1001,22 @@ Expression *ArrayLengthExp::optimize(int result)
return e;
}
Expression *EqualExp::optimize(int result)
{ Expression *e;
Expression *EqualExp::optimize(int result, bool keepLvalue)
{
//printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
e = this;
Expression *e1 = fromConstInitializer(result, this->e1);
Expression *e2 = fromConstInitializer(result, this->e2);
e = Equal(op, type, e1, e2);
Expression *e = Equal(op, type, e1, e2);
if (e == EXP_CANT_INTERPRET)
e = this;
return e;
}
Expression *IdentityExp::optimize(int result)
Expression *IdentityExp::optimize(int result, bool keepLvalue)
{
//printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
@@ -1032,7 +1049,13 @@ void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr)
else if (arr->op == TOKarrayliteral)
len = ((ArrayLiteralExp *)arr)->elements->dim;
else
return; // we don't know the length yet
{
Type *t = arr->type->toBasetype();
if (t->ty == Tsarray)
len = ((TypeSArray *)t)->dim->toInteger();
else
return; // we don't know the length yet
}
Expression *dollar = new IntegerExp(0, len, Type::tsize_t);
lengthVar->init = new ExpInitializer(0, dollar);
@@ -1040,7 +1063,7 @@ void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr)
}
Expression *IndexExp::optimize(int result)
Expression *IndexExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
@@ -1060,6 +1083,8 @@ Expression *IndexExp::optimize(int result)
// We might know $ now
setLengthVarIfKnown(lengthVar, e1);
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
if (keepLvalue)
return this;
e = Index(type, e1, e2);
if (e == EXP_CANT_INTERPRET)
e = this;
@@ -1067,7 +1092,7 @@ Expression *IndexExp::optimize(int result)
}
Expression *SliceExp::optimize(int result)
Expression *SliceExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
@@ -1094,7 +1119,7 @@ Expression *SliceExp::optimize(int result)
return e;
}
Expression *AndAndExp::optimize(int result)
Expression *AndAndExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("AndAndExp::optimize(%d) %s\n", result, toChars());
@@ -1134,7 +1159,7 @@ Expression *AndAndExp::optimize(int result)
return e;
}
Expression *OrOrExp::optimize(int result)
Expression *OrOrExp::optimize(int result, bool keepLvalue)
{ Expression *e;
e1 = e1->optimize(WANTflags | (result & WANTinterpret));
@@ -1170,7 +1195,7 @@ Expression *OrOrExp::optimize(int result)
return e;
}
Expression *CmpExp::optimize(int result)
Expression *CmpExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("CmpExp::optimize() %s\n", toChars());
@@ -1186,7 +1211,7 @@ Expression *CmpExp::optimize(int result)
return e;
}
Expression *CatExp::optimize(int result)
Expression *CatExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("CatExp::optimize(%d) %s\n", result, toChars());
@@ -1199,17 +1224,17 @@ Expression *CatExp::optimize(int result)
}
Expression *CondExp::optimize(int result)
Expression *CondExp::optimize(int result, bool keepLvalue)
{ Expression *e;
econd = econd->optimize(WANTflags | (result & WANTinterpret));
if (econd->isBool(TRUE))
e = e1->optimize(result);
e = e1->optimize(result, keepLvalue);
else if (econd->isBool(FALSE))
e = e2->optimize(result);
e = e2->optimize(result, keepLvalue);
else
{ e1 = e1->optimize(result);
e2 = e2->optimize(result);
{ e1 = e1->optimize(result, keepLvalue);
e2 = e2->optimize(result, keepLvalue);
e = this;
}
return e;
+549 -299
View File
File diff suppressed because it is too large Load Diff
+3 -4
View File
@@ -68,15 +68,16 @@ struct Parser : Lexer
int inBrackets; // inside [] of array index or slice
Loc lookingForElse; // location of lonely if looking for an else
Parser(Module *module, unsigned char *base, unsigned length, int doDocComment);
Parser(Module *module, unsigned char *base, size_t length, int doDocComment);
Dsymbols *parseModule();
Dsymbols *parseDeclDefs(int once);
Dsymbols *parseAutoDeclarations(StorageClass storageClass, unsigned char *comment);
Dsymbols *parseBlock();
void composeStorageClass(StorageClass stc);
StorageClass parseAttribute();
StorageClass parseAttribute(Expressions **pexps);
StorageClass parsePostfix();
StorageClass parseTypeCtor();
Expression *parseConstraint();
TemplateDeclaration *parseTemplateDeclaration(int ismixin);
TemplateParameters *parseTemplateParameterList(int flag = 0);
@@ -92,7 +93,6 @@ struct Parser : Lexer
Condition *parseVersionCondition();
Condition *parseStaticIfCondition();
Dsymbol *parseCtor();
PostBlitDeclaration *parsePostBlit();
DtorDeclaration *parseDtor();
StaticCtorDeclaration *parseStaticCtor();
StaticDtorDeclaration *parseStaticDtor();
@@ -126,7 +126,6 @@ struct Parser : Lexer
int isDeclarator(Token **pt, int *haveId, enum TOK endtok);
int isParameters(Token **pt);
int isExpression(Token **pt);
int isTemplateInstance(Token *t, Token **pt);
int skipParens(Token *t, Token **pt);
int skipAttributes(Token *t, Token **pt);
+13 -15
View File
@@ -13,7 +13,7 @@
#include <string.h>
#include <assert.h>
#if (defined (__SVR4) && defined (__sun))
#if defined (__sun)
#include <alloca.h>
#endif
@@ -59,16 +59,15 @@ Array::~Array()
}
void Array::mark()
{ unsigned u;
{
mem.mark(data);
for (u = 0; u < dim; u++)
for (size_t u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
void Array::reserve(unsigned nentries)
void Array::reserve(size_t nentries)
{
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries);
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
if (allocdim - dim < nentries)
{
if (allocdim == 0)
@@ -95,7 +94,7 @@ void Array::reserve(unsigned nentries)
}
}
void Array::setDim(unsigned newdim)
void Array::setDim(size_t newdim)
{
if (dim < newdim)
{
@@ -141,7 +140,7 @@ void Array::shift(void *ptr)
dim++;
}
void Array::insert(unsigned index, void *ptr)
void Array::insert(size_t index, void *ptr)
{
reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
@@ -150,12 +149,11 @@ void Array::insert(unsigned index, void *ptr)
}
void Array::insert(unsigned index, Array *a)
void Array::insert(size_t index, Array *a)
{
if (a)
{ unsigned d;
d = a->dim;
{
size_t d = a->dim;
reserve(d);
if (dim != index)
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
@@ -174,7 +172,7 @@ void Array::append(Array *a)
insert(dim, a);
}
void Array::remove(unsigned i)
void Array::remove(size_t i)
{
if (dim - i - 1)
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
@@ -183,8 +181,8 @@ void Array::remove(unsigned i)
char *Array::toChars()
{
unsigned len;
unsigned u;
size_t len;
size_t u;
char **buf;
char *str;
char *p;
+3 -3
View File
@@ -13,7 +13,7 @@
#include <string.h>
#include <assert.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include <unistd.h>
#include <pthread.h>
#endif
@@ -135,7 +135,7 @@ void Mem::check(void *p)
void Mem::error()
{
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
assert(0);
#endif
printf("Error: out of memory\n");
@@ -288,7 +288,7 @@ void Mem::operator delete(void *p)
/* ===================== linux ================================ */
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include <pthread.h>
+3 -3
View File
@@ -377,7 +377,7 @@ bool operator!=(longdouble x, longdouble y)
int _isnan(longdouble ld)
{
return (ld.exponent == 0x7fff && ld.mantissa != 0);
return (ld.exponent == 0x7fff && ld.mantissa != 0 && ld.mantissa != (1LL << 63)); // exclude pseudo-infinity and infinity, but not FP Indefinite
}
longdouble fabsl(longdouble ld)
@@ -514,7 +514,7 @@ int ld_type(longdouble x)
return LD_TYPE_SNAN;
}
int ld_sprint(char* str, int fmt, longdouble x)
size_t ld_sprint(char* str, int fmt, longdouble x)
{
// fmt is 'a','A','f' or 'g'
if(fmt != 'a' && fmt != 'A')
@@ -537,7 +537,7 @@ int ld_sprint(char* str, int fmt, longdouble x)
return sprintf(str, x.sign ? "-INF" : "INF");
}
int len = 0;
size_t len = 0;
if(x.sign)
str[len++] = '-';
len += sprintf(str + len, mantissa & (1LL << 63) ? "0x1." : "0x0.");
+3 -3
View File
@@ -18,7 +18,7 @@
typedef real_t longdouble;
template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
inline int ld_sprint(char* str, int fmt, longdouble x)
inline size_t ld_sprint(char* str, int fmt, longdouble x)
{
if(fmt == 'a' || fmt == 'A')
return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max
@@ -34,7 +34,7 @@ typedef volatile long double volatile_longdouble;
// template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
#define ldouble(x) ((longdouble)(x))
inline int ld_sprint(char* str, int fmt, longdouble x)
inline size_t ld_sprint(char* str, int fmt, longdouble x)
{
char sfmt[4] = "%Lg";
sfmt[2] = fmt;
@@ -247,7 +247,7 @@ public:
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
int ld_sprint(char* str, int fmt, longdouble x);
size_t ld_sprint(char* str, int fmt, longdouble x);
#endif // !_MSC_VER
+1 -1
View File
@@ -26,7 +26,7 @@ void browse(const char *url)
#endif
#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#if linux || __FreeBSD__ || __OpenBSD__ || __sun
#include <sys/types.h>
#include <sys/wait.h>
+14 -5
View File
@@ -1,10 +1,11 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
#include "port.h"
#if __DMC__
#include <math.h>
#include <float.h>
@@ -12,6 +13,7 @@
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
double Port::nan = NAN;
double Port::infinity = INFINITY;
@@ -127,6 +129,7 @@ char *Port::strupr(char *s)
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <stdlib.h>
#include <limits> // for std::numeric_limits
@@ -343,6 +346,7 @@ char *Port::strupr(char *s)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <wchar.h>
#include <float.h>
#include <assert.h>
@@ -384,7 +388,7 @@ int Port::isNan(double r)
#else
return __inline_isnan(r);
#endif
#elif defined __HAIKU__ || __OpenBSD__
#elif __HAIKU__ || __OpenBSD__
return isnan(r);
#else
#undef isnan
@@ -400,7 +404,7 @@ int Port::isNan(longdouble r)
#else
return __inline_isnan(r);
#endif
#elif defined __HAIKU__ || __OpenBSD__
#elif __HAIKU__ || __OpenBSD__
return isnan(r);
#else
#undef isnan
@@ -522,7 +526,7 @@ char *Port::strupr(char *s)
#endif
#if __sun&&__SVR4
#if __sun
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
#include <math.h>
@@ -532,6 +536,7 @@ char *Port::strupr(char *s)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <wchar.h>
#include <float.h>
#include <ieeefp.h>
@@ -614,6 +619,11 @@ double Port::pow(double x, double y)
return ::pow(x, y);
}
longdouble Port::fmodl(longdouble x, longdouble y)
{
return ::fmodl(x, y);
}
unsigned long long Port::strtoull(const char *p, char **pend, int base)
{
return ::strtoull(p, pend, base);
@@ -660,4 +670,3 @@ char *Port::strupr(char *s)
}
#endif
+6 -11
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -12,26 +12,21 @@
#include "longdouble.h"
#ifndef TYPEDEFS
#define TYPEDEFS
#include <wchar.h>
#if _MSC_VER
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#include <float.h> // for _isnan
#include <malloc.h> // for alloca
// According to VC 8.0 docs, long double is the same as double
longdouble strtold(const char *p,char **endp);
#define strtof strtod
#define isnan _isnan
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
typedef double d_time;
struct Port
+5 -6
View File
@@ -20,7 +20,7 @@
#include <io.h>
#endif
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
@@ -66,8 +66,8 @@
struct Narg
{
int argc; /* arg count */
int argvmax; /* dimension of nargv[] */
size_t argc; // arg count
size_t argvmax; // dimension of nargv[]
char **argv;
};
@@ -91,17 +91,16 @@ static int addargp(struct Narg *n, char *p)
return 0;
}
int response_expand(int *pargc, char ***pargv)
int response_expand(size_t *pargc, char ***pargv)
{
struct Narg n;
int i;
char *cp;
int recurse = 0;
n.argc = 0;
n.argvmax = 0; /* dimension of n.argv[] */
n.argv = NULL;
for(i=0; i<*pargc; ++i)
for (size_t i = 0; i < *pargc; ++i)
{
cp = (*pargv)[i];
if (*cp == '@')
+1 -1
View File
@@ -11,7 +11,7 @@
#include <stdlib.h>
#include <string.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include "../root/rmem.h"
#else
#include "rmem.h"
+111 -120
View File
@@ -8,7 +8,7 @@
// See the included readme.txt for details.
#ifndef POSIX
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun)
#endif
#include <stdio.h>
@@ -20,7 +20,7 @@
#include <assert.h>
#include <ctype.h>
#if (defined (__SVR4) && defined (__sun))
#if defined (__sun)
#include <alloca.h>
#endif
@@ -62,68 +62,6 @@ extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
#endif
/*************************************
* Convert wchar string to ascii string.
*/
char *wchar2ascii(wchar_t *us)
{
return wchar2ascii(us, wcslen(us));
}
char *wchar2ascii(wchar_t *us, unsigned len)
{
unsigned i;
char *p;
p = (char *)mem.malloc(len + 1);
for (i = 0; i <= len; i++)
p[i] = (char) us[i];
return p;
}
int wcharIsAscii(wchar_t *us)
{
return wcharIsAscii(us, wcslen(us));
}
int wcharIsAscii(wchar_t *us, unsigned len)
{
unsigned i;
for (i = 0; i <= len; i++)
{
if (us[i] & ~0xFF) // if high bits set
return 0; // it's not ascii
}
return 1;
}
/***********************************
* Compare length-prefixed strings (bstr).
*/
int bstrcmp(unsigned char *b1, unsigned char *b2)
{
return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1;
}
/***************************************
* Convert bstr into a malloc'd string.
*/
char *bstr2str(unsigned char *b)
{
char *s;
unsigned len;
len = *b;
s = (char *) mem.malloc(len + 1);
s[len] = 0;
return (char *)memcpy(s,b + 1,len);
}
/**************************************
* Print error message and exit.
*/
@@ -142,11 +80,6 @@ void error(const char *format, ...)
exit(EXIT_FAILURE);
}
void error_mem()
{
error("out of memory");
}
/**************************************
* Print warning message.
*/
@@ -206,10 +139,9 @@ void Object::mark()
/****************************** String ********************************/
String::String(char *str, int ref)
String::String(char *str)
: str(mem.strdup(str))
{
this->str = ref ? str : mem.strdup(str);
this->ref = ref;
}
String::~String()
@@ -269,7 +201,7 @@ hash_t String::hashCode()
return calcHash(str, strlen(str));
}
unsigned String::len()
size_t String::len()
{
return strlen(str);
}
@@ -297,8 +229,8 @@ void String::print()
/****************************** FileName ********************************/
FileName::FileName(char *str, int ref)
: String(str,ref)
FileName::FileName(char *str)
: String(str)
{
}
@@ -332,11 +264,6 @@ char *FileName::combine(const char *path, const char *name)
return f;
}
FileName::FileName(char *path, char *name)
: String(combine(path,name),1)
{
}
// Split a path into an Array of paths
Strings *FileName::splitPath(const char *path)
{
@@ -684,7 +611,7 @@ FileName *FileName::defaultExt(const char *name, const char *ext)
e = FileName::ext(name);
if (e) // if already has an extension
return new FileName((char *)name, 0);
return new FileName((char *)name);
len = strlen(name);
extlen = strlen(ext);
@@ -692,7 +619,7 @@ FileName *FileName::defaultExt(const char *name, const char *ext)
memcpy(s,name,len);
s[len] = '.';
memcpy(s + len + 1, ext, extlen + 1);
return new FileName(s, 0);
return new FileName(s);
}
/***************************
@@ -714,7 +641,7 @@ FileName *FileName::forceExt(const char *name, const char *ext)
s = (char *)alloca(len + extlen + 1);
memcpy(s,name,len);
memcpy(s + len, ext, extlen + 1);
return new FileName(s, 0);
return new FileName(s);
}
else
return defaultExt(name, ext); // doesn't have one
@@ -986,9 +913,20 @@ char *FileName::canonicalName(const char *name)
#endif
#elif _WIN32
/* Apparently, there is no good way to do this on Windows.
* GetFullPathName isn't it.
* GetFullPathName isn't it, but use it anyway.
*/
assert(0);
DWORD result = GetFullPathName(name, 0, NULL, NULL);
if (result)
{
char *buf = (char *)malloc(result);
result = GetFullPathName(name, result, buf, NULL);
if (result == 0)
{
free(buf);
return NULL;
}
return buf;
}
return NULL;
#else
assert(0);
@@ -1014,7 +952,7 @@ File::File(char *n)
buffer = NULL;
len = 0;
touchtime = NULL;
name = new FileName(n, 0);
name = new FileName(n);
}
File::~File()
@@ -1354,7 +1292,7 @@ err:
void File::readv()
{
if (read())
error("Error reading file '%s'\n",name->toChars());
error("Error reading file '%s'",name->toChars());
}
/**************************************
@@ -1369,13 +1307,13 @@ void File::mmreadv()
void File::writev()
{
if (write())
error("Error writing file '%s'\n",name->toChars());
error("Error writing file '%s'",name->toChars());
}
void File::appendv()
{
if (write())
error("Error appending to file '%s'\n",name->toChars());
error("Error appending to file '%s'",name->toChars());
}
/*******************************************
@@ -1424,7 +1362,7 @@ void File::remove()
Files *File::match(char *n)
{
return match(new FileName(n, 0));
return match(new FileName(n));
}
Files *File::match(FileName *n)
@@ -1524,6 +1462,10 @@ OutBuffer::OutBuffer()
data = NULL;
offset = 0;
size = 0;
doindent = 0;
level = 0;
linehead = 1;
}
OutBuffer::~OutBuffer()
@@ -1547,7 +1489,7 @@ void OutBuffer::mark()
mem.mark(data);
}
void OutBuffer::reserve(unsigned nbytes)
void OutBuffer::reserve(size_t nbytes)
{
//printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
if (size - offset < nbytes)
@@ -1562,13 +1504,26 @@ void OutBuffer::reset()
offset = 0;
}
void OutBuffer::setsize(unsigned size)
void OutBuffer::setsize(size_t size)
{
offset = size;
}
void OutBuffer::write(const void *data, unsigned nbytes)
void OutBuffer::write(const void *data, size_t nbytes)
{
if (doindent && linehead)
{
if (level)
{
reserve(level);
for (size_t i=0; i<level; i++)
{
this->data[offset] = '\t';
offset++;
}
}
linehead = 0;
}
reserve(nbytes);
memcpy(this->data + offset, data, nbytes);
offset += nbytes;
@@ -1585,9 +1540,8 @@ void OutBuffer::writestring(const char *string)
}
void OutBuffer::prependstring(const char *string)
{ unsigned len;
len = strlen(string);
{
size_t len = strlen(string);
reserve(len);
memmove(data + len, data, offset);
memcpy(data, string, len);
@@ -1601,10 +1555,26 @@ void OutBuffer::writenl()
#else
writeByte('\n');
#endif
if (doindent)
linehead = 1;
}
void OutBuffer::writeByte(unsigned b)
{
if (doindent && linehead
&& b != '\n')
{
if (level)
{
reserve(level);
for (size_t i=0; i<level; i++)
{
this->data[offset] = '\t';
offset++;
}
}
linehead = 0;
}
reserve(1);
this->data[offset] = (unsigned char)b;
offset++;
@@ -1672,6 +1642,24 @@ void OutBuffer::prependbyte(unsigned b)
void OutBuffer::writeword(unsigned w)
{
if (doindent && linehead
#if _WIN32
&& w != 0x0A0D)
#else
&& w != '\n')
#endif
{
if (level)
{
reserve(level);
for (size_t i=0; i<level; i++)
{
this->data[offset] = '\t';
offset++;
}
}
linehead = 0;
}
reserve(2);
*(unsigned short *)(this->data + offset) = (unsigned short)w;
offset += 2;
@@ -1697,6 +1685,24 @@ void OutBuffer::writeUTF16(unsigned w)
void OutBuffer::write4(unsigned w)
{
if (doindent && linehead
#if _WIN32
&& w != 0x000A000D)
#else
)
#endif
{
if (level)
{
reserve(level);
for (size_t i=0; i<level; i++)
{
this->data[offset] = '\t';
offset++;
}
}
linehead = 0;
}
reserve(4);
*(unsigned *)(this->data + offset) = w;
offset += 4;
@@ -1719,17 +1725,16 @@ void OutBuffer::write(Object *obj)
}
}
void OutBuffer::fill0(unsigned nbytes)
void OutBuffer::fill0(size_t nbytes)
{
reserve(nbytes);
memset(data + offset,0,nbytes);
offset += nbytes;
}
void OutBuffer::align(unsigned size)
{ unsigned nbytes;
nbytes = ((offset + size - 1) & ~(size - 1)) - offset;
void OutBuffer::align(size_t size)
{
size_t nbytes = ((offset + size - 1) & ~(size - 1)) - offset;
fill0(nbytes);
}
@@ -1831,7 +1836,7 @@ void OutBuffer::bracket(char left, char right)
* Return index just past right.
*/
unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right)
size_t OutBuffer::bracket(size_t i, const char *left, size_t j, const char *right)
{
size_t leftlen = strlen(left);
size_t rightlen = strlen(right);
@@ -1841,7 +1846,7 @@ unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char
return j + leftlen + rightlen;
}
void OutBuffer::spread(unsigned offset, unsigned nbytes)
void OutBuffer::spread(size_t offset, size_t nbytes)
{
reserve(nbytes);
memmove(data + offset + nbytes, data + offset,
@@ -1853,14 +1858,14 @@ void OutBuffer::spread(unsigned offset, unsigned nbytes)
* Returns: offset + nbytes
*/
unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes)
size_t OutBuffer::insert(size_t offset, const void *p, size_t nbytes)
{
spread(offset, nbytes);
memmove(data + offset, p, nbytes);
return offset + nbytes;
}
void OutBuffer::remove(unsigned offset, unsigned nbytes)
void OutBuffer::remove(size_t offset, size_t nbytes)
{
memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
this->offset -= nbytes;
@@ -1872,6 +1877,7 @@ char *OutBuffer::toChars()
return (char *)data;
}
// TODO: Remove (only used by disabled GC)
/********************************* Bits ****************************/
Bits::Bits()
@@ -1964,18 +1970,3 @@ void Bits::sub(Bits *b)
for (u = 0; u < allocdim; u++)
data[u] &= ~b->data[u];
}
+42 -58
View File
@@ -15,6 +15,7 @@
#ifdef DEBUG
#include <assert.h>
#endif
#include "port.h"
#if __DMC__
#pragma once
@@ -22,38 +23,6 @@
typedef size_t hash_t;
#include "longdouble.h"
char *wchar2ascii(wchar_t *);
int wcharIsAscii(wchar_t *);
char *wchar2ascii(wchar_t *, unsigned len);
int wcharIsAscii(wchar_t *, unsigned len);
int bstrcmp(unsigned char *s1, unsigned char *s2);
char *bstr2str(unsigned char *b);
#ifndef TYPEDEFS
#define TYPEDEFS
#if _MSC_VER
#include <float.h> // for _isnan
#include <malloc.h> // for alloca
// According to VC 8.0 docs, long double is the same as double
longdouble strtold(const char *p,char **endp);
#define strtof strtod
#define isnan _isnan
typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
#else
typedef long long longlong;
typedef unsigned long long ulonglong;
#endif
#endif
longlong randomx();
/*
* Root of our class library.
*/
@@ -107,17 +76,15 @@ struct Object
struct String : Object
{
int ref; // != 0 if this is a reference to someone else's string
char *str; // the string itself
String(char *str, int ref = 1);
String(char *str);
~String();
static hash_t calcHash(const char *str, size_t len);
static hash_t calcHash(const char *str);
hash_t hashCode();
unsigned len();
size_t len();
int equals(Object *obj);
int compare(Object *obj);
char *toChars();
@@ -127,8 +94,7 @@ struct String : Object
struct FileName : String
{
FileName(char *str, int ref);
FileName(char *path, char *name);
FileName(char *str);
hash_t hashCode();
int equals(Object *obj);
static int equals(const char *name1, const char *name2);
@@ -161,7 +127,7 @@ struct File : Object
{
int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file
unsigned len; // amount of data in buffer[]
size_t len; // amount of data in buffer[]
void *touchtime; // system time to use for file
FileName *name; // name of our file
@@ -251,7 +217,7 @@ struct File : Object
/* Set buffer
*/
void setbuffer(void *buffer, unsigned len)
void setbuffer(void *buffer, size_t len)
{
this->buffer = (unsigned char *)buffer;
this->len = len;
@@ -265,18 +231,20 @@ struct File : Object
struct OutBuffer : Object
{
unsigned char *data;
unsigned offset;
unsigned size;
size_t offset;
size_t size;
int doindent, level, linehead;
OutBuffer();
~OutBuffer();
char *extractData();
void mark();
void reserve(unsigned nbytes);
void setsize(unsigned size);
void reserve(size_t nbytes);
void setsize(size_t size);
void reset();
void write(const void *data, unsigned nbytes);
void write(const void *data, size_t nbytes);
void writebstring(unsigned char *string);
void writestring(const char *string);
void prependstring(const char *string);
@@ -290,26 +258,26 @@ struct OutBuffer : Object
void write4(unsigned w);
void write(OutBuffer *buf);
void write(Object *obj);
void fill0(unsigned nbytes);
void align(unsigned size);
void fill0(size_t nbytes);
void align(size_t size);
void vprintf(const char *format, va_list args);
void printf(const char *format, ...);
void bracket(char left, char right);
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
void spread(unsigned offset, unsigned nbytes);
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
void remove(unsigned offset, unsigned nbytes);
size_t bracket(size_t i, const char *left, size_t j, const char *right);
void spread(size_t offset, size_t nbytes);
size_t insert(size_t offset, const void *data, size_t nbytes);
void remove(size_t offset, size_t nbytes);
char *toChars();
char *extractString();
};
struct Array : Object
{
unsigned dim;
size_t dim;
void **data;
private:
unsigned allocdim;
size_t allocdim;
#define SMALLARRAYCAP 1
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
@@ -320,16 +288,16 @@ struct Array : Object
void mark();
char *toChars();
void reserve(unsigned nentries);
void setDim(unsigned newdim);
void reserve(size_t nentries);
void setDim(size_t newdim);
void fixDim();
void push(void *ptr);
void *pop();
void shift(void *ptr);
void insert(unsigned index, void *ptr);
void insert(unsigned index, Array *a);
void insert(size_t index, void *ptr);
void insert(size_t index, Array *a);
void append(Array *a);
void remove(unsigned i);
void remove(size_t i);
void zero();
void *tos();
void sort();
@@ -376,8 +344,24 @@ struct ArrayBase : Array
{
return (ArrayBase *)Array::copy();
}
typedef int (*ArrayBase_apply_ft_t)(TYPE *, void *);
int apply(ArrayBase_apply_ft_t fp, void *param)
{
for (size_t i = 0; i < dim; i++)
{ TYPE *e = (*this)[i];
if (e)
{
if (e->apply(fp, param))
return 1;
}
}
return 0;
}
};
// TODO: Remove (only used by disabled GC)
struct Bits : Object
{
unsigned bitdim;
+1 -1
View File
@@ -12,7 +12,7 @@
#include <stdlib.h>
#include <assert.h>
#if __sun&&__SVR4 || _MSC_VER
#if __sun || _MSC_VER
#include <alloca.h>
#endif
+10 -11
View File
@@ -17,6 +17,7 @@
#include "rmem.h" // mem
#include "stringtable.h"
// TODO: Merge with root.String
hash_t calcHash(const char *str, size_t len)
{
hash_t hash = 0;
@@ -66,14 +67,14 @@ hash_t calcHash(const char *str, size_t len)
}
}
void StringValue::ctor(const char *p, unsigned length)
void StringValue::ctor(const char *p, size_t length)
{
this->length = length;
this->lstring[length] = 0;
memcpy(this->lstring, p, length * sizeof(char));
}
void StringTable::init(unsigned size)
void StringTable::init(size_t size)
{
table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size;
@@ -82,11 +83,9 @@ void StringTable::init(unsigned size)
StringTable::~StringTable()
{
unsigned i;
// Zero out dangling pointers to help garbage collector.
// Should zero out StringEntry's too.
for (i = 0; i < count; i++)
for (size_t i = 0; i < count; i++)
table[i] = NULL;
mem.free(table);
@@ -101,10 +100,10 @@ struct StringEntry
StringValue value;
static StringEntry *alloc(const char *s, unsigned len);
static StringEntry *alloc(const char *s, size_t len);
};
StringEntry *StringEntry::alloc(const char *s, unsigned len)
StringEntry *StringEntry::alloc(const char *s, size_t len)
{
StringEntry *se;
@@ -114,7 +113,7 @@ StringEntry *StringEntry::alloc(const char *s, unsigned len)
return se;
}
void **StringTable::search(const char *s, unsigned len)
void **StringTable::search(const char *s, size_t len)
{
hash_t hash;
unsigned u;
@@ -148,7 +147,7 @@ void **StringTable::search(const char *s, unsigned len)
return (void **)se;
}
StringValue *StringTable::lookup(const char *s, unsigned len)
StringValue *StringTable::lookup(const char *s, size_t len)
{ StringEntry *se;
se = *(StringEntry **)search(s,len);
@@ -158,7 +157,7 @@ StringValue *StringTable::lookup(const char *s, unsigned len)
return NULL;
}
StringValue *StringTable::update(const char *s, unsigned len)
StringValue *StringTable::update(const char *s, size_t len)
{ StringEntry **pse;
StringEntry *se;
@@ -172,7 +171,7 @@ StringValue *StringTable::update(const char *s, unsigned len)
return &se->value;
}
StringValue *StringTable::insert(const char *s, unsigned len)
StringValue *StringTable::insert(const char *s, size_t len)
{ StringEntry **pse;
StringEntry *se;
+10 -10
View File
@@ -30,7 +30,7 @@ struct StringValue
char *string;
};
private:
unsigned length;
size_t length;
#ifndef IN_GCC
#if _MSC_VER
@@ -41,33 +41,33 @@ private:
char lstring[];
public:
unsigned len() const { return length; }
size_t len() const { return length; }
const char *toDchars() const { return lstring; }
private:
friend struct StringEntry;
StringValue(); // not constructible
// This is more like a placement new c'tor
void ctor(const char *p, unsigned length);
void ctor(const char *p, size_t length);
};
struct StringTable
{
private:
void **table;
unsigned count;
unsigned tabledim;
size_t count;
size_t tabledim;
public:
void init(unsigned size = 37);
void init(size_t size = 37);
~StringTable();
StringValue *lookup(const char *s, unsigned len);
StringValue *insert(const char *s, unsigned len);
StringValue *update(const char *s, unsigned len);
StringValue *lookup(const char *s, size_t len);
StringValue *insert(const char *s, size_t len);
StringValue *update(const char *s, size_t len);
private:
void **search(const char *s, unsigned len);
void **search(const char *s, size_t len);
};
#endif
+41 -17
View File
@@ -68,9 +68,9 @@ Scope::Scope()
this->protection = PROTpublic;
this->explicitProtection = 0;
this->stc = 0;
this->depmsg = NULL;
this->offset = 0;
this->inunion = 0;
this->incontract = 0;
this->nofree = 0;
this->noctor = 0;
this->noaccesscheck = 0;
@@ -84,6 +84,7 @@ Scope::Scope()
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = NULL;
this->userAttributes = NULL;
}
Scope::Scope(Scope *enclosing)
@@ -117,10 +118,10 @@ Scope::Scope(Scope *enclosing)
this->linkage = enclosing->linkage;
this->protection = enclosing->protection;
this->explicitProtection = enclosing->explicitProtection;
this->depmsg = enclosing->depmsg;
this->stc = enclosing->stc;
this->offset = 0;
this->inunion = enclosing->inunion;
this->incontract = enclosing->incontract;
this->nofree = 0;
this->noctor = enclosing->noctor;
this->noaccesscheck = enclosing->noaccesscheck;
@@ -130,10 +131,11 @@ Scope::Scope(Scope *enclosing)
this->parameterSpecialization = enclosing->parameterSpecialization;
this->ignoreTemplates = enclosing->ignoreTemplates;
this->callSuper = enclosing->callSuper;
this->flags = 0;
this->flags = (enclosing->flags & SCOPEcontract);
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
this->userAttributes = enclosing->userAttributes;
assert(this != enclosing);
}
@@ -200,25 +202,48 @@ void Scope::mergeCallSuper(Loc loc, unsigned cs)
// The two paths are callSuper and cs; the result is merged into callSuper.
if (cs != callSuper)
{ int a;
int b;
{ // Have ALL branches called a constructor?
int aAll = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
int bAll = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
callSuper |= cs & (CSXany_ctor | CSXlabel);
if (cs & CSXreturn)
{
// Have ANY branches called a constructor?
bool aAny = (cs & CSXany_ctor) != 0;
bool bAny = (callSuper & CSXany_ctor) != 0;
// Have any branches returned?
bool aRet = (cs & CSXreturn) != 0;
bool bRet = (callSuper & CSXreturn) != 0;
bool ok = true;
// If one has returned without a constructor call, there must be never
// have been ctor calls in the other.
if ( (aRet && !aAny && bAny) ||
(bRet && !bAny && aAny))
{ ok = false;
}
else if (callSuper & CSXreturn)
// If one branch has called a ctor and then exited, anything the
// other branch has done is OK (except returning without a
// ctor call, but we already checked that).
else if (aRet && aAll)
{
callSuper |= cs & (CSXany_ctor | CSXlabel);
}
else if (bRet && bAll)
{
callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
}
else
{
a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0;
b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
if (a != b)
error(loc, "one path skips constructor");
callSuper |= cs;
{ // Both branches must have called ctors, or both not.
ok = (aAll == bAll);
// If one returned without a ctor, we must remember that
// (Don't bother if we've already found an error)
if (ok && aRet && !aAny)
callSuper |= CSXreturn;
callSuper |= cs & (CSXany_ctor | CSXlabel);
}
if (!ok)
error(loc, "one path skips constructor");
}
}
@@ -257,8 +282,7 @@ Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
s = sc->scopesym->search(loc, ident, 0);
if (s)
{
if ((global.params.warnings ||
global.params.Dversion > 1) &&
if (global.params.Dversion > 1 &&
ident == Id::length &&
sc->scopesym->isArrayScopeSymbol() &&
sc->enclosing &&
+7 -1
View File
@@ -68,7 +68,6 @@ struct Scope
// set in a pass after semantic() on all fields so they can be
// semantic'd in any order.
int inunion; // we're processing members of a union
int incontract; // we're inside contract code
int nofree; // set if shouldn't free it
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
@@ -94,6 +93,7 @@ struct Scope
int explicitProtection; // set if in an explicit protection attribute
StorageClass stc; // storage class
char *depmsg; // customized deprecation message
unsigned flags;
#define SCOPEctor 1 // constructor type
@@ -102,9 +102,15 @@ struct Scope
#define SCOPEstaticassert 8 // inside static assert
#define SCOPEdebug 0x10 // inside debug conditional
#define SCOPEinvariant 0x20 // inside invariant code
#define SCOPErequire 0x40 // inside in contract code
#define SCOPEensure 0x60 // inside out contract code
#define SCOPEcontract 0x60 // [mask] we're inside contract code
#ifdef IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
Expressions *userAttributes; // user defined attributes
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
+246 -149
View File
File diff suppressed because it is too large Load Diff
+59 -49
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -114,18 +114,18 @@ struct Statement : Object
void print();
char *toChars();
void error(const char *format, ...) IS_PRINTF(2);
void warning(const char *format, ...) IS_PRINTF(2);
void error(const char *format, ...);
void warning(const char *format, ...);
void deprecation(const char *format, ...);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
int incontract;
virtual ScopeStatement *isScopeStatement() { return NULL; }
virtual Statement *semantic(Scope *sc);
Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
Statement *semanticNoScope(Scope *sc);
virtual int hasBreak();
virtual int hasContinue();
virtual int usesEH();
virtual Statement *getRelatedLabeled() { return this; }
virtual bool hasBreak();
virtual bool hasContinue();
virtual bool usesEH();
virtual int blockExit(bool mustNotThrow);
virtual int comeFrom();
virtual int isEmpty();
@@ -152,6 +152,7 @@ struct Statement : Object
virtual LabelStatement *isLabelStatement() { return NULL; }
#if IN_LLVM
virtual AsmBlockStatement *isAsmBlockStatement() { return NULL; }
virtual void toNakedIR(IRState *irs);
virtual AsmBlockStatement* endsWithAsm();
#endif
@@ -226,7 +227,7 @@ struct CompoundStatement : Statement
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
int isEmpty();
@@ -267,9 +268,9 @@ struct UnrolledLoopStatement : Statement
UnrolledLoopStatement(Loc loc, Statements *statements);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -292,9 +293,9 @@ struct ScopeStatement : Statement
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
ScopeStatement *isScopeStatement() { return this; }
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
int isEmpty();
@@ -316,9 +317,9 @@ struct WhileStatement : Statement
WhileStatement(Loc loc, Expression *c, Statement *b);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -337,9 +338,9 @@ struct DoStatement : Statement
DoStatement(Loc loc, Statement *b, Expression *c);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -358,14 +359,20 @@ struct ForStatement : Statement
Statement *body;
int nest;
// When wrapped in try/finally clauses, this points to the outermost one,
// which may have an associated label. Internal break/continue statements
// treat that label as referring to this loop.
Statement *relatedLabeled;
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
Statement *syntaxCopy();
Statement *semanticInit(Scope *sc);
Statement *semantic(Scope *sc);
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
int hasBreak();
int hasContinue();
int usesEH();
Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; }
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -399,9 +406,9 @@ struct ForeachStatement : Statement
bool checkForArgTypes();
int inferAggregate(Scope *sc, Dsymbol *&sapply);
int inferApplyArgTypes(Scope *sc, Dsymbol *&sapply);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -427,9 +434,9 @@ struct ForeachRangeStatement : Statement
Expression *lwr, Expression *upr, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -455,7 +462,7 @@ struct IfStatement : Statement
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
IfStatement *isIfStatement() { return this; }
@@ -477,7 +484,7 @@ struct ConditionalStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -492,7 +499,7 @@ struct PragmaStatement : Statement
PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -534,8 +541,8 @@ struct SwitchStatement : Statement
SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int usesEH();
bool hasBreak();
bool usesEH();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -561,7 +568,7 @@ struct CaseStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int compare(Object *obj);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -608,7 +615,7 @@ struct DefaultStatement : Statement
DefaultStatement(Loc loc, Statement *s);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
@@ -731,9 +738,9 @@ struct SynchronizedStatement : Statement
SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -758,7 +765,7 @@ struct WithStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
@@ -775,8 +782,8 @@ struct TryCatchStatement : Statement
TryCatchStatement(Loc loc, Statement *body, Catches *catches);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int hasBreak();
int usesEH();
bool hasBreak();
bool usesEH();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
@@ -793,7 +800,8 @@ struct Catch : Object
Identifier *ident;
VarDeclaration *var;
Statement *handler;
bool internalCatch;
bool internalCatch; // was generated by the compiler,
// wasn't present in source code
Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
Catch *syntaxCopy();
@@ -811,9 +819,9 @@ struct TryFinallyStatement : Statement
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
int hasBreak();
int hasContinue();
int usesEH();
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
@@ -832,7 +840,7 @@ struct OnScopeStatement : Statement
int blockExit(bool mustNotThrow);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
int usesEH();
bool usesEH();
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
Expression *interpret(InterState *istate);
@@ -842,6 +850,8 @@ struct OnScopeStatement : Statement
struct ThrowStatement : Statement
{
Expression *exp;
bool internalThrow; // was generated by the compiler,
// wasn't present in source code
ThrowStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
@@ -921,7 +931,7 @@ struct LabelStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
int usesEH();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
+7
View File
@@ -58,6 +58,7 @@ void StaticAssert::semantic2(Scope *sc)
sc->flags |= SCOPEstaticassert;
++sc->ignoreTemplates;
Expression *e = exp->semantic(sc);
e = resolveProperties(sc, e);
sc = sc->pop();
if (!e->type->checkBoolean())
{
@@ -78,8 +79,14 @@ void StaticAssert::semantic2(Scope *sc)
OutBuffer buf;
msg = msg->semantic(sc);
msg = resolveProperties(sc, msg);
msg = msg->ctfeInterpret();
hgs.console = 1;
StringExp * s = msg->toString();
if (s)
{ s->postfix = 0; // Don't display a trailing 'c'
msg = s;
}
msg->toCBuffer(&buf, &hgs);
error("%s", buf.toChars());
}
+64 -48
View File
@@ -49,7 +49,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
stag = NULL;
sinit = NULL;
#endif
isnested = 0;
isnested = false;
vthis = NULL;
#if DMDV2
@@ -71,6 +71,13 @@ enum PROT AggregateDeclaration::prot()
return protection;
}
void AggregateDeclaration::setScope(Scope *sc)
{
if (sizeok == SIZEOKdone)
return;
ScopeDsymbol::setScope(sc);
}
void AggregateDeclaration::semantic2(Scope *sc)
{
//printf("AggregateDeclaration::semantic2(%s)\n", toChars());
@@ -84,6 +91,7 @@ void AggregateDeclaration::semantic2(Scope *sc)
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
//printf("\t[%d] %s\n", i, s->toChars());
s->semantic2(sc);
}
sc->pop();
@@ -157,6 +165,10 @@ unsigned AggregateDeclaration::size(Loc loc)
*/
struct SV
{
/* Returns:
* 0 this member doesn't need further processing to determine struct size
* 1 this member does
*/
static int func(Dsymbol *s, void *param)
{ SV *psv = (SV *)param;
VarDeclaration *v = s->isVarDeclaration();
@@ -164,7 +176,7 @@ unsigned AggregateDeclaration::size(Loc loc)
{
if (v->scope)
v->semantic(NULL);
if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCconst | STCimmutable | STCmanifest | STCctfe | STCtemplateparameter))
if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCctfe | STCtemplateparameter))
return 0;
if (v->storage_class & STCfield && v->sem >= SemanticDone)
return 0;
@@ -272,8 +284,6 @@ unsigned AggregateDeclaration::placeField(
;
else if (8 < memalignsize)
memalignsize = 8;
else if (alignment < memalignsize)
memalignsize = alignment;
}
else
{
@@ -295,6 +305,7 @@ unsigned AggregateDeclaration::placeField(
int AggregateDeclaration::isNested()
{
assert((isnested & ~1) == 0);
return isnested;
}
@@ -403,7 +414,9 @@ void StructDeclaration::semantic(Scope *sc)
assert(type);
if (!members) // if forward reference
{
return;
}
if (symtab)
{ if (sizeok == SIZEOKdone || !scope)
@@ -452,50 +465,15 @@ void StructDeclaration::semantic(Scope *sc)
assert(!isAnonymous());
if (sc->stc & STCabstract)
error("structs, unions cannot be abstract");
userAttributes = sc->userAttributes;
if (sizeok == SIZEOKnone) // if not already done the addMember step
{
int hasfunctions = 0;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
//printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
s->addMember(sc, this, 1);
if (s->isFuncDeclaration())
hasfunctions = 1;
}
// If nested struct, add in hidden 'this' pointer to outer scope
if (hasfunctions && !(storage_class & STCstatic))
{ Dsymbol *s = toParent2();
if (s)
{
AggregateDeclaration *ad = s->isAggregateDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
TemplateInstance *ti;
if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd)
{ isnested = 1;
Type *t;
if (ad)
t = ad->handle;
else if (fd)
{ AggregateDeclaration *ad = fd->isMember2();
if (ad)
t = ad->handle;
else
t = Type::tvoidptr;
}
else
assert(0);
if (t->ty == Tstruct)
t = Type::tvoidptr; // t should not be a ref type
assert(!vthis);
vthis = new ThisDeclaration(loc, t);
//vthis->storage_class |= STCref;
members->push(vthis);
}
}
}
}
@@ -508,13 +486,12 @@ void StructDeclaration::semantic(Scope *sc)
sc2->protection = PROTpublic;
sc2->explicitProtection = 0;
sc2->structalign = STRUCTALIGN_DEFAULT;
size_t members_dim = members->dim;
sc2->userAttributes = NULL;
/* Set scope so if there are forward references, we still might be able to
* resolve individual members like enums.
*/
for (size_t i = 0; i < members_dim; i++)
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
/* There are problems doing this in the general case because
* Scope keeps track of things like 'offset'
@@ -526,7 +503,7 @@ void StructDeclaration::semantic(Scope *sc)
}
}
for (size_t i = 0; i < members_dim; i++)
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
@@ -535,7 +512,7 @@ void StructDeclaration::semantic(Scope *sc)
* field was processed. The problem is the chicken-and-egg determination
* of when that is. See Bugzilla 7426 for more info.
*/
if (i + 1 == members_dim)
if (i + 1 == members->dim)
{
if (sizeok == SIZEOKnone && s->isAliasDeclaration())
finalizeSize(sc2);
@@ -670,7 +647,7 @@ void StructDeclaration::semantic(Scope *sc)
postblit = buildPostBlit(sc2);
cpctor = buildCpCtor(sc2);
buildOpAssign(sc2);
hasIdentityAssign = (buildOpAssign(sc2) != NULL);
hasIdentityEquals = (buildOpEquals(sc2) != NULL);
xeq = buildXopEquals(sc2);
@@ -764,6 +741,45 @@ void StructDeclaration::finalizeSize(Scope *sc)
sizeok = SIZEOKdone;
}
void StructDeclaration::makeNested()
{
if (!isnested && sizeok != SIZEOKdone)
{
// If nested struct, add in hidden 'this' pointer to outer scope
if (!(storage_class & STCstatic))
{ Dsymbol *s = toParent2();
if (s)
{
AggregateDeclaration *ad = s->isAggregateDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
TemplateInstance *ti;
if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd)
{ isnested = true;
Type *t;
if (ad)
t = ad->handle;
else if (fd)
{ AggregateDeclaration *ad = fd->isMember2();
if (ad)
t = ad->handle;
else
t = Type::tvoidptr;
}
else
assert(0);
if (t->ty == Tstruct)
t = Type::tvoidptr; // t should not be a ref type
assert(!vthis);
vthis = new ThisDeclaration(loc, t);
//vthis->storage_class |= STCref;
members->push(vthis);
}
}
}
}
}
/***************************************
* Return true if struct is POD (Plain Old Data).
* This is defined as:
@@ -820,13 +836,13 @@ void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
buf->writenl();
buf->level++;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
buf->level--;
buf->writeByte('}');
buf->writenl();
}
+416 -137
View File
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -40,6 +40,7 @@ struct Expression;
struct AliasDeclaration;
struct FuncDeclaration;
struct HdrGenState;
struct Parameter;
enum MATCH;
enum PASS;
@@ -68,6 +69,7 @@ struct TemplateDeclaration : ScopeDsymbol
int literal; // this template declaration is a literal
int ismixin; // template declaration is only to be used as a mixin
enum PROT protection;
struct Previous
{ Previous *prev;
@@ -95,7 +97,7 @@ struct TemplateDeclaration : ScopeDsymbol
MATCH deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
Object *declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Expressions *fargs);
TemplateDeclaration *isTemplateDeclaration() { return this; }
@@ -304,7 +306,6 @@ struct TemplateInstance : ScopeDsymbol
int havetempdecl; // 1 if used second constructor
Dsymbol *isnested; // if referencing local symbols, this is the context
int speculative; // 1 if only instantiated with errors gagged
bool ignore; // true if the instance must be ignored when codegen'ing
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
will be emitted in the output or not before the symbol
@@ -350,6 +351,7 @@ struct TemplateInstance : ScopeDsymbol
AliasDeclaration *isAliasDeclaration();
#if IN_LLVM
bool ignore; // true if the instance must be ignored when codegen'ing
Module* tmodule; // module from outermost enclosing template instantiation
Module* emittedInModule; // which module this template instance has been emitted in
@@ -392,6 +394,7 @@ Expression *isExpression(Object *o);
Dsymbol *isDsymbol(Object *o);
Type *isType(Object *o);
Tuple *isTuple(Object *o);
Parameter *isParameter(Object *o);
int arrayObjectIsError(Objects *args);
int isError(Object *o);
Type *getType(Object *o);
+89 -13
View File
@@ -61,11 +61,8 @@ static int fptraits(void *param, FuncDeclaration *f)
return 0;
Expression *e;
if (p->e1->op == TOKdotvar)
{ DotVarExp *dve = (DotVarExp *)p->e1;
e = new DotVarExp(0, dve->e1, new FuncAliasDeclaration(f, 0));
}
if (p->e1)
e = new DotVarExp(0, p->e1, new FuncAliasDeclaration(f, 0));
else
e = new DsymbolExp(0, new FuncAliasDeclaration(f, 0));
p->exps->push(e);
@@ -149,6 +146,28 @@ Expression *TraitsExp::semantic(Scope *sc)
{
ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
}
else if (ident == Id::isPOD)
{
if (dim != 1)
goto Ldimerror;
Object *o = (*args)[0];
Type *t = isType(o);
StructDeclaration *sd;
if (!t)
{
error("type expected as second argument of __traits %s instead of %s", ident->toChars(), o->toChars());
goto Lfalse;
}
if (t->toBasetype()->ty == Tstruct
&& ((sd = (StructDeclaration *)(((TypeStruct *)t->toBasetype())->sym)) != NULL))
{
if (sd->isPOD())
goto Ltrue;
else
goto Lfalse;
}
goto Ltrue;
}
else if (ident == Id::isAbstractFunction)
{
FuncDeclaration *f;
@@ -190,20 +209,52 @@ Expression *TraitsExp::semantic(Scope *sc)
else if (ident == Id::identifier)
{ // Get identifier for symbol as a string literal
// Specify 0 for the flags argument to semanticTiargs() so that
// a symbol should not be folded to a constant.
TemplateInstance::semanticTiargs(loc, sc, args, 0);
/* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
* a symbol should not be folded to a constant.
* Bit 1 means don't convert Parameter to Type if Parameter has an identifier
*/
TemplateInstance::semanticTiargs(loc, sc, args, 2);
if (dim != 1)
goto Ldimerror;
Object *o = (*args)[0];
Dsymbol *s = getDsymbol(o);
if (!s || !s->ident)
Parameter *po = isParameter(o);
Identifier *id;
if (po)
{ id = po->ident;
assert(id);
}
else
{
error("argument %s has no identifier", o->toChars());
Dsymbol *s = getDsymbol(o);
if (!s || !s->ident)
{
error("argument %s has no identifier", o->toChars());
goto Lfalse;
}
id = s->ident;
}
StringExp *se = new StringExp(loc, id->toChars());
return se->semantic(sc);
}
else if (ident == Id::getProtection)
{
if (dim != 1)
goto Ldimerror;
Object *o = (*args)[0];
Dsymbol *s = getDsymbol(o);
if (!s)
{
if (!isError(o))
error("argument %s has no protection", o->toChars());
goto Lfalse;
}
StringExp *se = new StringExp(loc, s->ident->toChars());
PROT protection = s->prot();
const char *protName = Pprotectionnames[protection];
StringExp *se = new StringExp(loc, (char *) protName);
return se->semantic(sc);
}
else if (ident == Id::parent)
@@ -213,7 +264,11 @@ Expression *TraitsExp::semantic(Scope *sc)
Object *o = (*args)[0];
Dsymbol *s = getDsymbol(o);
if (s)
{
if (FuncDeclaration *fd = s->isFuncDeclaration()) // Bugzilla 8943
s = fd->toAliasFunc();
s = s->toParent();
}
if (!s)
{
error("argument %s has no parent", o->toChars());
@@ -221,7 +276,6 @@ Expression *TraitsExp::semantic(Scope *sc)
}
return (new DsymbolExp(loc, s))->semantic(sc);
}
#endif
else if (ident == Id::hasMember ||
ident == Id::getMember ||
@@ -313,10 +367,15 @@ Expression *TraitsExp::semantic(Scope *sc)
if (e->op == TOKvar)
{ VarExp *ve = (VarExp *)e;
f = ve->var->isFuncDeclaration();
e = NULL;
}
else if (e->op == TOKdotvar)
{ DotVarExp *dve = (DotVarExp *)e;
f = dve->var->isFuncDeclaration();
if (dve->e1->op == TOKdottype || dve->e1->op == TOKthis)
e = NULL;
else
e = dve->e1;
}
else
f = NULL;
@@ -346,6 +405,23 @@ Expression *TraitsExp::semantic(Scope *sc)
}
return new IntegerExp(loc, cd->structsize, Type::tsize_t);
}
else if (ident == Id::getAttributes)
{
if (dim != 1)
goto Ldimerror;
Object *o = (*args)[0];
Dsymbol *s = getDsymbol(o);
if (!s)
{
error("first argument is not a symbol");
goto Lfalse;
}
//printf("getAttributes %s, %p\n", s->toChars(), s->userAttributes);
if (!s->userAttributes)
s->userAttributes = new Expressions();
TupleExp *tup = new TupleExp(loc, s->userAttributes);
return tup->semantic(sc);
}
else if (ident == Id::allMembers || ident == Id::derivedMembers)
{
if (dim != 1)
+1 -1
View File
@@ -230,7 +230,7 @@ const char *utf_decodeChar(utf8_t const *s, size_t len, size_t *pidx, dchar_t *p
//printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len);
// Get expected sequence length
unsigned n = UTF8_STRIDE[u];
size_t n = UTF8_STRIDE[u];
switch (n)
{
case 1: // ASCII
+9 -4
View File
@@ -32,11 +32,16 @@ cl::list<std::string> runargs("run",
cl::Positional,
cl::PositionalEatsArgs);
static cl::opt<bool, true> useDeprecated("d",
cl::desc("Allow deprecated language features"),
static cl::opt<ubyte, true> useDeprecated(
cl::desc("Allow deprecated code/language features:"),
cl::ZeroOrMore,
cl::location(global.params.useDeprecated));
cl::values(
clEnumValN(0, "de", "Do not allow deprecated features"),
clEnumValN(1, "d", "Silently allow deprecated features"),
clEnumValN(2, "dw", "Warn about the use of deprecated features"),
clEnumValEnd),
cl::location(global.params.useDeprecated),
cl::init(2));
#if DMDV2
cl::opt<bool, true> enforcePropertySyntax("property",
+4 -4
View File
@@ -69,7 +69,7 @@ namespace ls = llvm::sys;
// We reuse DMD's response file parsing routine for maximum compatibilty - it
// handles quotes in a very peciuliar way.
int response_expand(int *pargc, char ***pargv);
int response_expand(size_t *pargc, char ***pargv);
void browse(const char *url);
/**
@@ -395,10 +395,10 @@ struct Params
* Parses the flags from the given command line and the DFLAGS environment
* variable into a Params struct.
*/
Params parseArgs(int originalArgc, char** originalArgv, ls::Path ldcPath)
Params parseArgs(size_t originalArgc, char** originalArgv, ls::Path ldcPath)
{
// Expand any response files present into the list of arguments.
int argc = originalArgc;
size_t argc = originalArgc;
char** argv = originalArgv;
if (response_expand(&argc, &argv))
{
@@ -682,7 +682,7 @@ Params parseArgs(int originalArgc, char** originalArgv, ls::Path ldcPath)
else if (strcmp(p + 1, "run") == 0)
{
result.run = true;
int runargCount = (((int)i >= originalArgc) ? argc : originalArgc) - i - 1;
int runargCount = ((i >= originalArgc) ? argc : originalArgc) - i - 1;
if (runargCount)
{
result.files.push_back(argv[i + 1]);
+8 -1
View File
@@ -705,7 +705,14 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
fdecl->ir.irFunc->func = func;
// calling convention
if (!vafunc && fdecl->llvmInternal != LLVMintrinsic)
if (!vafunc && fdecl->llvmInternal != LLVMintrinsic
#if DMDV2
// DMD treats _Dmain as having C calling convention and this has been
// hardcoded into druntime, even if the frontend type has D linkage.
// See Bugzilla issue 9028.
&& !fdecl->isMain()
#endif
)
func->setCallingConv(DtoCallingConv(fdecl->loc, f->linkage));
else // fall back to C, it should be the right thing to do
func->setCallingConv(llvm::CallingConv::C);
+2 -1
View File
@@ -189,6 +189,7 @@ static void LLVM_D_BuildRuntimeModule()
LLType* objectTy = DtoType(ClassDeclaration::object->type);
LLType* classInfoTy = DtoType(ClassDeclaration::classinfo->type);
LLType* typeInfoTy = DtoType(Type::typeinfo->type);
LLType* aaTypeInfoTy = DtoType(Type::typeinfoassociativearray->type);
LLType* aaTy = rt_ptr(LLStructType::get(gIR->context()));
@@ -1013,7 +1014,7 @@ static void LLVM_D_BuildRuntimeModule()
{
llvm::StringRef fname("_d_assocarrayliteralTX");
std::vector<LLType*> types;
types.push_back(typeInfoTy);
types.push_back(aaTypeInfoTy);
types.push_back(voidArrayTy);
types.push_back(voidArrayTy);
LLFunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
+2 -1
View File
@@ -3115,7 +3115,8 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p)
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assocarrayliteralTX");
LLFunctionType* funcTy = func->getFunctionType();
LLValue* aaTypeInfo = DtoTypeInfoOf(stripModifiers(aatype));
LLValue* aaTypeInfo = DtoBitCast(DtoTypeInfoOf(stripModifiers(aatype)),
DtoType(Type::typeinfoassociativearray->type));
LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
+2 -1
View File
@@ -86,7 +86,6 @@ file(GLOB_RECURSE DCRT_D ${RUNTIME_DC_DIR}/*.d)
file(GLOB_RECURSE LDC_D ${RUNTIME_DIR}/src/ldc/*.d)
list(REMOVE_ITEM DCRT_D
${RUNTIME_DC_DIR}/alloca.d
${RUNTIME_DC_DIR}/critical_.d
${RUNTIME_DC_DIR}/deh.d
${RUNTIME_DC_DIR}/deh2.d
${RUNTIME_DC_DIR}/llmath.d
@@ -128,6 +127,7 @@ if(PHOBOS2_DIR)
endif()
file(GLOB PHOBOS2_D ${PHOBOS2_DIR}/std/*.d)
file(GLOB PHOBOS2_D_DIGEST ${PHOBOS2_DIR}/std/digest/*.d)
file(GLOB PHOBOS2_D_NET ${PHOBOS2_DIR}/std/net/*.d)
file(GLOB_RECURSE PHOBOS2_D_INTERNAL ${PHOBOS2_DIR}/std/internal/*.d)
file(GLOB PHOBOS2_D_C ${PHOBOS2_DIR}/std/c/*.d)
@@ -151,6 +151,7 @@ if(PHOBOS2_DIR)
file(GLOB PHOBOS2_D_WIN ${PHOBOS2_DIR}/std/windows/*.d)
endif()
list(APPEND PHOBOS2_D
${PHOBOS2_D_DIGEST}
${PHOBOS2_D_NET}
${PHOBOS2_D_INTERNAL}
${PHOBOS2_D_WIN}