mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-18 19:30:20 +02:00
Merged 2.061 frontend.
This commit is contained in:
+7
-5
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+149
-64
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+220
-110
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+70
-52
@@ -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
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -26,5 +26,7 @@ class Library
|
||||
virtual void write() = 0;
|
||||
};
|
||||
|
||||
Library *LibMSCoff_factory();
|
||||
|
||||
#endif /* DMD_LIB_H */
|
||||
|
||||
|
||||
+21
-20
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+22
-5
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+3
-4
@@ -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
@@ -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
@@ -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>
|
||||
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+59
-49
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+5
-2
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) };
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
+1
-1
Submodule runtime/druntime updated: 5c6053c546...e2d17024e2
+1
-1
Submodule runtime/phobos updated: c3574a7bc6...1a3eba6a18
+1
-1
Submodule tests/d2/dmd-testsuite updated: b6f7ffbfa8...0424040e52
Reference in New Issue
Block a user