mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-10-15 14:37:00 +02:00
fixes #432 :: apply DMDFE 1.063; thanks SiegeLord
This commit is contained in:
@@ -620,6 +620,8 @@ Dsymbol *AliasDeclaration::toAlias()
|
||||
{ error("recursive alias declaration");
|
||||
aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL);
|
||||
}
|
||||
else if (!aliassym && scope)
|
||||
semantic(scope);
|
||||
Dsymbol *s = aliassym ? aliassym->toAlias() : this;
|
||||
return s;
|
||||
}
|
||||
@@ -1356,6 +1358,9 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
|
||||
#endif
|
||||
#endif
|
||||
//printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
|
||||
// __dollar creates problems because it isn't a real variable Bugzilla 3326
|
||||
if (ident == Id::dollar)
|
||||
::error(loc, "cannnot use $ inside a function literal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-1
@@ -106,6 +106,14 @@ int overloadApply(Module* from, FuncDeclaration *fstart,
|
||||
int (*fp)(void *, FuncDeclaration *),
|
||||
void *param);
|
||||
|
||||
enum Semantic
|
||||
{
|
||||
SemanticStart, // semantic has not been run
|
||||
SemanticIn, // semantic() is in progress
|
||||
SemanticDone, // semantic() has been run
|
||||
Semantic2Done, // semantic2() has been run
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct Declaration : Dsymbol
|
||||
@@ -612,6 +620,13 @@ struct TypeInfoSharedDeclaration : TypeInfoDeclaration
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
};
|
||||
|
||||
struct TypeInfoWildDeclaration : TypeInfoDeclaration
|
||||
{
|
||||
TypeInfoWildDeclaration(Type *tinfo);
|
||||
|
||||
void toDt(dt_t **pdt);
|
||||
};
|
||||
#endif
|
||||
|
||||
/**************************************************************/
|
||||
@@ -756,6 +771,8 @@ struct FuncDeclaration : Declaration
|
||||
int isCodeseg();
|
||||
int isOverloadable();
|
||||
int isPure();
|
||||
int isSafe();
|
||||
int isTrusted();
|
||||
virtual int isNested();
|
||||
int needThis();
|
||||
virtual int isVirtual();
|
||||
@@ -930,6 +947,17 @@ struct StaticCtorDeclaration : FuncDeclaration
|
||||
StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct SharedStaticCtorDeclaration : StaticCtorDeclaration
|
||||
{
|
||||
SharedStaticCtorDeclaration(Loc loc, Loc endloc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct StaticDtorDeclaration : FuncDeclaration
|
||||
{ VarDeclaration *vgate; // 'gate' variable
|
||||
|
||||
@@ -948,6 +976,17 @@ struct StaticDtorDeclaration : FuncDeclaration
|
||||
StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct SharedStaticDtorDeclaration : StaticDtorDeclaration
|
||||
{
|
||||
SharedStaticDtorDeclaration(Loc loc, Loc endloc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct InvariantDeclaration : FuncDeclaration
|
||||
{
|
||||
InvariantDeclaration(Loc loc, Loc endloc);
|
||||
@@ -963,7 +1002,6 @@ struct InvariantDeclaration : FuncDeclaration
|
||||
InvariantDeclaration *isInvariantDeclaration() { return this; }
|
||||
};
|
||||
|
||||
|
||||
struct UnitTestDeclaration : FuncDeclaration
|
||||
{
|
||||
UnitTestDeclaration(Loc loc, Loc endloc);
|
||||
|
||||
@@ -301,6 +301,10 @@ void Dsymbol::importAll(Scope *sc)
|
||||
* Does semantic analysis on the public face of declarations.
|
||||
*/
|
||||
|
||||
void Dsymbol::semantic0(Scope *sc)
|
||||
{
|
||||
}
|
||||
|
||||
void Dsymbol::semantic(Scope *sc)
|
||||
{
|
||||
error("%p has no semantic routine", this);
|
||||
|
||||
@@ -163,6 +163,7 @@ struct Dsymbol : Object
|
||||
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
virtual void setScope(Scope *sc);
|
||||
virtual void importAll(Scope *sc);
|
||||
virtual void semantic0(Scope *sc);
|
||||
virtual void semantic(Scope *sc);
|
||||
virtual void semantic2(Scope *sc);
|
||||
virtual void semantic3(Scope *sc);
|
||||
|
||||
+28
@@ -51,6 +51,34 @@ Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
|
||||
return ed;
|
||||
}
|
||||
|
||||
void EnumDeclaration::semantic0(Scope *sc)
|
||||
{
|
||||
/* This function is a hack to get around a significant problem.
|
||||
* The members of anonymous enums, like:
|
||||
* enum { A, B, C }
|
||||
* don't get installed into the symbol table until after they are
|
||||
* semantically analyzed, yet they're supposed to go into the enclosing
|
||||
* scope's table. Hence, when forward referenced, they come out as
|
||||
* 'undefined'. The real fix is to add them in at addSymbol() time.
|
||||
* But to get code to compile, we'll just do this quick hack at the moment
|
||||
* to compile it if it doesn't depend on anything else.
|
||||
*/
|
||||
|
||||
if (isdone || !scope)
|
||||
return;
|
||||
if (!isAnonymous() || memtype)
|
||||
return;
|
||||
for (int i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
|
||||
if (em && em->value)
|
||||
return;
|
||||
}
|
||||
|
||||
// Can do it
|
||||
semantic(sc);
|
||||
}
|
||||
|
||||
void EnumDeclaration::semantic(Scope *sc)
|
||||
{ int i;
|
||||
uinteger_t number;
|
||||
|
||||
@@ -47,6 +47,7 @@ struct EnumDeclaration : ScopeDsymbol
|
||||
|
||||
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic0(Scope *sc);
|
||||
void semantic(Scope *sc);
|
||||
int oneMember(Dsymbol **ps);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
+5
-142
@@ -60,148 +60,6 @@ Expression *expandVar(int result, VarDeclaration *v);
|
||||
|
||||
#define LOGSEMANTIC 0
|
||||
|
||||
/**********************************
|
||||
* Set operator precedence for each operator.
|
||||
*/
|
||||
|
||||
// Operator precedence - greater values are higher precedence
|
||||
|
||||
enum PREC
|
||||
{
|
||||
PREC_zero,
|
||||
PREC_expr,
|
||||
PREC_assign,
|
||||
PREC_cond,
|
||||
PREC_oror,
|
||||
PREC_andand,
|
||||
PREC_or,
|
||||
PREC_xor,
|
||||
PREC_and,
|
||||
PREC_equal,
|
||||
PREC_rel,
|
||||
PREC_shift,
|
||||
PREC_add,
|
||||
PREC_mul,
|
||||
PREC_unary,
|
||||
PREC_primary,
|
||||
};
|
||||
|
||||
enum PREC precedence[TOKMAX];
|
||||
|
||||
void initPrecedence()
|
||||
{
|
||||
precedence[TOKdotvar] = PREC_primary;
|
||||
precedence[TOKimport] = PREC_primary;
|
||||
precedence[TOKidentifier] = PREC_primary;
|
||||
precedence[TOKthis] = PREC_primary;
|
||||
precedence[TOKsuper] = PREC_primary;
|
||||
precedence[TOKint64] = PREC_primary;
|
||||
precedence[TOKfloat64] = PREC_primary;
|
||||
precedence[TOKnull] = PREC_primary;
|
||||
precedence[TOKstring] = PREC_primary;
|
||||
precedence[TOKarrayliteral] = PREC_primary;
|
||||
precedence[TOKtypeid] = PREC_primary;
|
||||
precedence[TOKis] = PREC_primary;
|
||||
precedence[TOKassert] = PREC_primary;
|
||||
precedence[TOKfunction] = PREC_primary;
|
||||
precedence[TOKvar] = PREC_primary;
|
||||
#if DMDV2
|
||||
precedence[TOKdefault] = PREC_primary;
|
||||
#endif
|
||||
|
||||
// post
|
||||
precedence[TOKdotti] = PREC_primary;
|
||||
precedence[TOKdot] = PREC_primary;
|
||||
// precedence[TOKarrow] = PREC_primary;
|
||||
precedence[TOKplusplus] = PREC_primary;
|
||||
precedence[TOKminusminus] = PREC_primary;
|
||||
precedence[TOKcall] = PREC_primary;
|
||||
precedence[TOKslice] = PREC_primary;
|
||||
precedence[TOKarray] = PREC_primary;
|
||||
|
||||
precedence[TOKaddress] = PREC_unary;
|
||||
precedence[TOKstar] = PREC_unary;
|
||||
precedence[TOKneg] = PREC_unary;
|
||||
precedence[TOKuadd] = PREC_unary;
|
||||
precedence[TOKnot] = PREC_unary;
|
||||
precedence[TOKtobool] = PREC_add;
|
||||
precedence[TOKtilde] = PREC_unary;
|
||||
precedence[TOKdelete] = PREC_unary;
|
||||
precedence[TOKnew] = PREC_unary;
|
||||
precedence[TOKcast] = PREC_unary;
|
||||
|
||||
precedence[TOKmul] = PREC_mul;
|
||||
precedence[TOKdiv] = PREC_mul;
|
||||
precedence[TOKmod] = PREC_mul;
|
||||
|
||||
precedence[TOKadd] = PREC_add;
|
||||
precedence[TOKmin] = PREC_add;
|
||||
precedence[TOKcat] = PREC_add;
|
||||
|
||||
precedence[TOKshl] = PREC_shift;
|
||||
precedence[TOKshr] = PREC_shift;
|
||||
precedence[TOKushr] = PREC_shift;
|
||||
|
||||
precedence[TOKlt] = PREC_rel;
|
||||
precedence[TOKle] = PREC_rel;
|
||||
precedence[TOKgt] = PREC_rel;
|
||||
precedence[TOKge] = PREC_rel;
|
||||
precedence[TOKunord] = PREC_rel;
|
||||
precedence[TOKlg] = PREC_rel;
|
||||
precedence[TOKleg] = PREC_rel;
|
||||
precedence[TOKule] = PREC_rel;
|
||||
precedence[TOKul] = PREC_rel;
|
||||
precedence[TOKuge] = PREC_rel;
|
||||
precedence[TOKug] = PREC_rel;
|
||||
precedence[TOKue] = PREC_rel;
|
||||
precedence[TOKin] = PREC_rel;
|
||||
|
||||
#if 0
|
||||
precedence[TOKequal] = PREC_equal;
|
||||
precedence[TOKnotequal] = PREC_equal;
|
||||
precedence[TOKidentity] = PREC_equal;
|
||||
precedence[TOKnotidentity] = PREC_equal;
|
||||
#else
|
||||
/* Note that we changed precedence, so that < and != have the same
|
||||
* precedence. This change is in the parser, too.
|
||||
*/
|
||||
precedence[TOKequal] = PREC_rel;
|
||||
precedence[TOKnotequal] = PREC_rel;
|
||||
precedence[TOKidentity] = PREC_rel;
|
||||
precedence[TOKnotidentity] = PREC_rel;
|
||||
#endif
|
||||
|
||||
precedence[TOKand] = PREC_and;
|
||||
|
||||
precedence[TOKxor] = PREC_xor;
|
||||
|
||||
precedence[TOKor] = PREC_or;
|
||||
|
||||
precedence[TOKandand] = PREC_andand;
|
||||
|
||||
precedence[TOKoror] = PREC_oror;
|
||||
|
||||
precedence[TOKquestion] = PREC_cond;
|
||||
|
||||
precedence[TOKassign] = PREC_assign;
|
||||
precedence[TOKconstruct] = PREC_assign;
|
||||
precedence[TOKblit] = PREC_assign;
|
||||
precedence[TOKaddass] = PREC_assign;
|
||||
precedence[TOKminass] = PREC_assign;
|
||||
precedence[TOKcatass] = PREC_assign;
|
||||
precedence[TOKmulass] = PREC_assign;
|
||||
precedence[TOKdivass] = PREC_assign;
|
||||
precedence[TOKmodass] = PREC_assign;
|
||||
precedence[TOKshlass] = PREC_assign;
|
||||
precedence[TOKshrass] = PREC_assign;
|
||||
precedence[TOKushrass] = PREC_assign;
|
||||
precedence[TOKandass] = PREC_assign;
|
||||
precedence[TOKorass] = PREC_assign;
|
||||
precedence[TOKxorass] = PREC_assign;
|
||||
|
||||
precedence[TOKcomma] = PREC_expr;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* Given var, we need to get the
|
||||
* right 'this' pointer if var is in an outer class, but our
|
||||
@@ -6225,6 +6083,11 @@ Expression *DelegateExp::semantic(Scope *sc)
|
||||
AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
|
||||
if (func->needThis())
|
||||
e1 = getRightThis(loc, sc, ad, e1, func);
|
||||
if (ad && ad->isClassDeclaration() && ad->type != e1->type)
|
||||
{ // A downcast is required for interfaces, see Bugzilla 3706
|
||||
e1 = new CastExp(loc, e1, ad->type);
|
||||
e1 = e1->semantic(sc);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
+24
-6
@@ -1101,7 +1101,6 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (fensure)
|
||||
{ returnLabel = new LabelDsymbol(Id::returnLabel);
|
||||
LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
|
||||
ls->isReturnLabel = 1;
|
||||
returnLabel->statement = ls;
|
||||
}
|
||||
sc2 = sc2->pop();
|
||||
@@ -1283,19 +1282,38 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
#else
|
||||
Type *t = argptr->type;
|
||||
VarDeclaration *p;
|
||||
unsigned offset;
|
||||
unsigned offset = 0;
|
||||
|
||||
Expression *e1 = new VarExp(0, argptr);
|
||||
// Find the last non-ref parameter
|
||||
if (parameters && parameters->dim)
|
||||
p = (VarDeclaration *)parameters->data[parameters->dim - 1];
|
||||
{
|
||||
int lastNonref = parameters->dim -1;
|
||||
p = (VarDeclaration *)parameters->data[lastNonref];
|
||||
/* The trouble with out and ref parameters is that taking
|
||||
* the address of it doesn't work, because later processing
|
||||
* adds in an extra level of indirection. So we skip over them.
|
||||
*/
|
||||
while (p->storage_class & (STCout | STCref))
|
||||
{
|
||||
--lastNonref;
|
||||
offset += PTRSIZE;
|
||||
if (lastNonref < 0)
|
||||
{
|
||||
p = v_arguments;
|
||||
break;
|
||||
}
|
||||
p = (VarDeclaration *)parameters->data[lastNonref];
|
||||
}
|
||||
}
|
||||
else
|
||||
p = v_arguments; // last parameter is _arguments[]
|
||||
if (p->storage_class & STClazy)
|
||||
// If the last parameter is lazy, it's the size of a delegate
|
||||
offset = PTRSIZE * 2;
|
||||
offset += PTRSIZE * 2;
|
||||
else
|
||||
offset = p->type->size();
|
||||
offset = (offset + 3) & ~3; // assume stack aligns on 4
|
||||
offset += p->type->size();
|
||||
offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size
|
||||
Expression *e = new SymOffExp(0, p, offset);
|
||||
e->type = Type::tvoidptr;
|
||||
//e = e->semantic(sc);
|
||||
|
||||
+1
-1
@@ -341,7 +341,7 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value)
|
||||
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
|
||||
{ unsigned i;
|
||||
unsigned length;
|
||||
const unsigned long amax = 0x80000000;
|
||||
const unsigned amax = 0x80000000;
|
||||
|
||||
//printf("ArrayInitializer::semantic(%s)\n", t->toChars());
|
||||
if (sem) // if semantic() already run
|
||||
|
||||
+7
-1
@@ -1112,8 +1112,9 @@ Expression *Expression::interpret(InterState *istate)
|
||||
|
||||
Expression *ThisExp::interpret(InterState *istate)
|
||||
{
|
||||
if (istate->localThis)
|
||||
if (istate && istate->localThis)
|
||||
return istate->localThis->interpret(istate);
|
||||
error("value of 'this' is not known at compile time");
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
|
||||
@@ -2106,6 +2107,11 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
#endif
|
||||
Expression *e = EXP_CANT_INTERPRET;
|
||||
Expression *e1 = this->e1;
|
||||
if (!istate)
|
||||
{
|
||||
error("value of %s is not known at compile time", e1->toChars());
|
||||
return e;
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ Global::Global()
|
||||
|
||||
copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
version = "v1.062";
|
||||
version = "v1.063";
|
||||
ldc_version = LDC_REV;
|
||||
llvm_version = LLVM_REV_STR;
|
||||
global.structalign = 8;
|
||||
|
||||
+20
-6
@@ -99,6 +99,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
||||
vmoduleinfo = NULL;
|
||||
#if IN_DMD
|
||||
massert = NULL;
|
||||
munittest = NULL;
|
||||
marray = NULL;
|
||||
sictor = NULL;
|
||||
sctor = NULL;
|
||||
@@ -387,15 +388,20 @@ void Module::read(Loc loc)
|
||||
{
|
||||
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
|
||||
if (srcfile->read())
|
||||
{ error(loc, "cannot read file '%s'", srcfile->toChars());
|
||||
if (!global.gag)
|
||||
{ error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
|
||||
if (!global.gag)
|
||||
{ /* Print path
|
||||
*/
|
||||
for (size_t i = 0; i < global.path->dim; i++)
|
||||
*/
|
||||
if (global.path)
|
||||
{
|
||||
for (int i = 0; i < global.path->dim; i++)
|
||||
{
|
||||
char *p = (char *)global.path->data[i];
|
||||
fprintf(stdmsg, "import path[%d] = %s\n", i, p);
|
||||
char *p = (char *)global.path->data[i];
|
||||
fprintf(stdmsg, "import path[%d] = %s\n", i, p);
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
|
||||
}
|
||||
fatal();
|
||||
}
|
||||
@@ -791,6 +797,14 @@ void Module::semantic(Scope *unused_sc)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Do semantic() on members that don't depend on others
|
||||
for (int i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
|
||||
//printf("\tModule('%s'): '%s'.semantic0()\n", toChars(), s->toChars());
|
||||
s->semantic0(sc);
|
||||
}
|
||||
|
||||
// Pass 1 semantic routines: do public side of the definition
|
||||
for (int i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
||||
|
||||
@@ -173,6 +173,9 @@ struct Module : Package
|
||||
Symbol *massert; // module assert function
|
||||
Symbol *toModuleAssert(); // get module assert function
|
||||
|
||||
Symbol *munittest; // module unittest failure function
|
||||
Symbol *toModuleUnittest(); // get module unittest failure function
|
||||
|
||||
Symbol *marray; // module array bounds function
|
||||
Symbol *toModuleArray(); // get module array bounds function
|
||||
|
||||
|
||||
@@ -4939,6 +4939,9 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
exps->reserve(sym->fields.dim);
|
||||
for (size_t i = 0; i < sym->fields.dim; i++)
|
||||
{ VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
|
||||
// Don't include hidden 'this' pointer
|
||||
if (v->isThisDeclaration())
|
||||
continue;
|
||||
Expression *fe = new DotVarExp(e->loc, e, v);
|
||||
exps->push(fe);
|
||||
}
|
||||
|
||||
+120
-1
@@ -5461,6 +5461,125 @@ void Parser::addComment(Dsymbol *s, unsigned char *blockComment)
|
||||
token.lineComment = NULL;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Set operator precedence for each operator.
|
||||
*/
|
||||
|
||||
enum PREC precedence[TOKMAX];
|
||||
|
||||
void initPrecedence()
|
||||
{
|
||||
precedence[TOKdotvar] = PREC_primary;
|
||||
precedence[TOKimport] = PREC_primary;
|
||||
precedence[TOKidentifier] = PREC_primary;
|
||||
precedence[TOKthis] = PREC_primary;
|
||||
precedence[TOKsuper] = PREC_primary;
|
||||
precedence[TOKint64] = PREC_primary;
|
||||
precedence[TOKfloat64] = PREC_primary;
|
||||
precedence[TOKnull] = PREC_primary;
|
||||
precedence[TOKstring] = PREC_primary;
|
||||
precedence[TOKarrayliteral] = PREC_primary;
|
||||
precedence[TOKtypeid] = PREC_primary;
|
||||
precedence[TOKis] = PREC_primary;
|
||||
precedence[TOKassert] = PREC_primary;
|
||||
precedence[TOKfunction] = PREC_primary;
|
||||
precedence[TOKvar] = PREC_primary;
|
||||
#if DMDV2
|
||||
precedence[TOKdefault] = PREC_primary;
|
||||
#endif
|
||||
|
||||
// post
|
||||
precedence[TOKdotti] = PREC_primary;
|
||||
precedence[TOKdot] = PREC_primary;
|
||||
// precedence[TOKarrow] = PREC_primary;
|
||||
precedence[TOKplusplus] = PREC_primary;
|
||||
precedence[TOKminusminus] = PREC_primary;
|
||||
precedence[TOKcall] = PREC_primary;
|
||||
precedence[TOKslice] = PREC_primary;
|
||||
precedence[TOKarray] = PREC_primary;
|
||||
|
||||
precedence[TOKaddress] = PREC_unary;
|
||||
precedence[TOKstar] = PREC_unary;
|
||||
precedence[TOKneg] = PREC_unary;
|
||||
precedence[TOKuadd] = PREC_unary;
|
||||
precedence[TOKnot] = PREC_unary;
|
||||
precedence[TOKtobool] = PREC_add;
|
||||
precedence[TOKtilde] = PREC_unary;
|
||||
precedence[TOKdelete] = PREC_unary;
|
||||
precedence[TOKnew] = PREC_unary;
|
||||
precedence[TOKcast] = PREC_unary;
|
||||
|
||||
precedence[TOKmul] = PREC_mul;
|
||||
precedence[TOKdiv] = PREC_mul;
|
||||
precedence[TOKmod] = PREC_mul;
|
||||
|
||||
precedence[TOKadd] = PREC_add;
|
||||
precedence[TOKmin] = PREC_add;
|
||||
precedence[TOKcat] = PREC_add;
|
||||
|
||||
precedence[TOKshl] = PREC_shift;
|
||||
precedence[TOKshr] = PREC_shift;
|
||||
precedence[TOKushr] = PREC_shift;
|
||||
|
||||
precedence[TOKlt] = PREC_rel;
|
||||
precedence[TOKle] = PREC_rel;
|
||||
precedence[TOKgt] = PREC_rel;
|
||||
precedence[TOKge] = PREC_rel;
|
||||
precedence[TOKunord] = PREC_rel;
|
||||
precedence[TOKlg] = PREC_rel;
|
||||
precedence[TOKleg] = PREC_rel;
|
||||
precedence[TOKule] = PREC_rel;
|
||||
precedence[TOKul] = PREC_rel;
|
||||
precedence[TOKuge] = PREC_rel;
|
||||
precedence[TOKug] = PREC_rel;
|
||||
precedence[TOKue] = PREC_rel;
|
||||
precedence[TOKin] = PREC_rel;
|
||||
|
||||
#if 0
|
||||
precedence[TOKequal] = PREC_equal;
|
||||
precedence[TOKnotequal] = PREC_equal;
|
||||
precedence[TOKidentity] = PREC_equal;
|
||||
precedence[TOKnotidentity] = PREC_equal;
|
||||
#else
|
||||
/* Note that we changed precedence, so that < and != have the same
|
||||
* precedence. This change is in the parser, too.
|
||||
*/
|
||||
precedence[TOKequal] = PREC_rel;
|
||||
precedence[TOKnotequal] = PREC_rel;
|
||||
precedence[TOKidentity] = PREC_rel;
|
||||
precedence[TOKnotidentity] = PREC_rel;
|
||||
#endif
|
||||
|
||||
precedence[TOKand] = PREC_and;
|
||||
|
||||
precedence[TOKxor] = PREC_xor;
|
||||
|
||||
precedence[TOKor] = PREC_or;
|
||||
|
||||
precedence[TOKandand] = PREC_andand;
|
||||
|
||||
precedence[TOKoror] = PREC_oror;
|
||||
|
||||
precedence[TOKquestion] = PREC_cond;
|
||||
|
||||
precedence[TOKassign] = PREC_assign;
|
||||
precedence[TOKconstruct] = PREC_assign;
|
||||
precedence[TOKblit] = PREC_assign;
|
||||
precedence[TOKaddass] = PREC_assign;
|
||||
precedence[TOKminass] = PREC_assign;
|
||||
precedence[TOKcatass] = PREC_assign;
|
||||
precedence[TOKmulass] = PREC_assign;
|
||||
precedence[TOKdivass] = PREC_assign;
|
||||
precedence[TOKmodass] = PREC_assign;
|
||||
precedence[TOKshlass] = PREC_assign;
|
||||
precedence[TOKshrass] = PREC_assign;
|
||||
precedence[TOKushrass] = PREC_assign;
|
||||
precedence[TOKandass] = PREC_assign;
|
||||
precedence[TOKorass] = PREC_assign;
|
||||
precedence[TOKxorass] = PREC_assign;
|
||||
|
||||
precedence[TOKcomma] = PREC_expr;
|
||||
}
|
||||
|
||||
|
||||
/********************************* ***************************/
|
||||
|
||||
|
||||
+26
@@ -143,4 +143,30 @@ struct Parser : Lexer
|
||||
void addComment(Dsymbol *s, unsigned char *blockComment);
|
||||
};
|
||||
|
||||
// Operator precedence - greater values are higher precedence
|
||||
|
||||
enum PREC
|
||||
{
|
||||
PREC_zero,
|
||||
PREC_expr,
|
||||
PREC_assign,
|
||||
PREC_cond,
|
||||
PREC_oror,
|
||||
PREC_andand,
|
||||
PREC_or,
|
||||
PREC_xor,
|
||||
PREC_and,
|
||||
PREC_equal,
|
||||
PREC_rel,
|
||||
PREC_shift,
|
||||
PREC_add,
|
||||
PREC_mul,
|
||||
PREC_unary,
|
||||
PREC_primary,
|
||||
};
|
||||
|
||||
extern enum PREC precedence[TOKMAX];
|
||||
|
||||
void initPrecedence();
|
||||
|
||||
#endif /* DMD_PARSE_H */
|
||||
|
||||
+147
-1
@@ -8,7 +8,6 @@
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <process.h>
|
||||
|
||||
@@ -113,6 +112,153 @@ unsigned __stdcall startthread(void *p)
|
||||
return EXIT_SUCCESS; // if skidding
|
||||
}
|
||||
|
||||
#elif linux // Posix
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
void *startthread(void *arg);
|
||||
|
||||
void err_abort(int status, const char *msg)
|
||||
{
|
||||
fprintf(stderr, "fatal error = %d, %s\n", status, msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct FileData
|
||||
{
|
||||
File *file;
|
||||
int result;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
int value;
|
||||
};
|
||||
|
||||
struct AsyncRead
|
||||
{
|
||||
static AsyncRead *create(size_t nfiles);
|
||||
void addFile(File *file);
|
||||
void start();
|
||||
int read(size_t i);
|
||||
static void dispose(AsyncRead *);
|
||||
|
||||
size_t filesdim;
|
||||
size_t filesmax;
|
||||
FileData files[1];
|
||||
};
|
||||
|
||||
|
||||
AsyncRead *AsyncRead::create(size_t nfiles)
|
||||
{
|
||||
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
|
||||
(nfiles - 1) * sizeof(FileData));
|
||||
aw->filesmax = nfiles;
|
||||
return aw;
|
||||
}
|
||||
|
||||
void AsyncRead::addFile(File *file)
|
||||
{
|
||||
//printf("addFile(file = %p)\n", file);
|
||||
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
||||
assert(filesdim < filesmax);
|
||||
FileData *f = &files[filesdim];
|
||||
f->file = file;
|
||||
|
||||
int status = pthread_mutex_init(&f->mutex, NULL);
|
||||
if (status != 0)
|
||||
err_abort(status, "init mutex");
|
||||
status = pthread_cond_init(&f->cond, NULL);
|
||||
if (status != 0)
|
||||
err_abort(status, "init cond");
|
||||
|
||||
filesdim++;
|
||||
}
|
||||
|
||||
void AsyncRead::start()
|
||||
{
|
||||
//printf("aw->filesdim = %p %d\n", this, filesdim);
|
||||
if (filesdim)
|
||||
{
|
||||
pthread_t thread_id;
|
||||
int status = pthread_create(&thread_id,
|
||||
NULL,
|
||||
&startthread,
|
||||
this);
|
||||
if (status != 0)
|
||||
err_abort(status, "create thread");
|
||||
}
|
||||
}
|
||||
|
||||
int AsyncRead::read(size_t i)
|
||||
{
|
||||
FileData *f = &files[i];
|
||||
|
||||
// Wait for the event
|
||||
int status = pthread_mutex_lock(&f->mutex);
|
||||
if (status != 0)
|
||||
err_abort(status, "lock mutex");
|
||||
while (f->value == 0)
|
||||
{
|
||||
status = pthread_cond_wait(&f->cond, &f->mutex);
|
||||
if (status != 0)
|
||||
err_abort(status, "wait on condition");
|
||||
}
|
||||
status = pthread_mutex_unlock(&f->mutex);
|
||||
if (status != 0)
|
||||
err_abort(status, "unlock mutex");
|
||||
|
||||
return f->result;
|
||||
}
|
||||
|
||||
void AsyncRead::dispose(AsyncRead *aw)
|
||||
{
|
||||
//printf("AsyncRead::dispose()\n");
|
||||
for (int i = 0; i < aw->filesdim; i++)
|
||||
{
|
||||
FileData *f = &aw->files[i];
|
||||
int status = pthread_cond_destroy(&f->cond);
|
||||
if (status != 0)
|
||||
err_abort(status, "cond destroy");
|
||||
status = pthread_mutex_destroy(&f->mutex);
|
||||
if (status != 0)
|
||||
err_abort(status, "mutex destroy");
|
||||
}
|
||||
delete aw;
|
||||
}
|
||||
|
||||
|
||||
void *startthread(void *p)
|
||||
{
|
||||
AsyncRead *aw = (AsyncRead *)p;
|
||||
|
||||
//printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim);
|
||||
size_t dim = aw->filesdim;
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ FileData *f = &aw->files[i];
|
||||
|
||||
f->result = f->file->read();
|
||||
|
||||
// Set event
|
||||
int status = pthread_mutex_lock(&f->mutex);
|
||||
if (status != 0)
|
||||
err_abort(status, "lock mutex");
|
||||
f->value = 1;
|
||||
status = pthread_cond_signal(&f->cond);
|
||||
if (status != 0)
|
||||
err_abort(status, "signal condition");
|
||||
status = pthread_mutex_unlock(&f->mutex);
|
||||
if (status != 0)
|
||||
err_abort(status, "unlock mutex");
|
||||
}
|
||||
|
||||
return NULL; // end thread
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
+6
-1
@@ -322,6 +322,9 @@ char *Port::strupr(char *s)
|
||||
#include <bits/nan.h>
|
||||
#include <bits/mathdef.h>
|
||||
#endif
|
||||
#if __FreeBSD__ && __i386__
|
||||
#include <ieeefp.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
@@ -355,11 +358,13 @@ PortInitializer::PortInitializer()
|
||||
foo = -foo; // turn off sign bit
|
||||
Port::nan = foo;
|
||||
|
||||
#if __FreeBSD__
|
||||
#if __FreeBSD__ && __i386__
|
||||
// LDBL_MAX comes out as infinity. Fix.
|
||||
static unsigned char x[sizeof(long double)] =
|
||||
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F };
|
||||
Port::ldbl_max = *(long double *)&x[0];
|
||||
// FreeBSD defaults to double precision. Switch to extended precision.
|
||||
fpsetprec(FP_PE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -31,6 +31,7 @@
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if POSIX
|
||||
@@ -966,7 +967,13 @@ void FileName::ensurePathExists(const char *path)
|
||||
#if POSIX
|
||||
if (mkdir(path, 0777))
|
||||
#endif
|
||||
error("cannot create directory %s", path);
|
||||
{
|
||||
/* Don't error out if another instance of dmd just created
|
||||
* this directory
|
||||
*/
|
||||
if (errno != EEXIST)
|
||||
error("cannot create directory %s", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -1896,7 +1896,12 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
*/
|
||||
Expressions *exps = new Expressions();
|
||||
exps->push(flde);
|
||||
e = new CallExp(loc, aggr, exps);
|
||||
if (aggr->op == TOKdelegate &&
|
||||
((DelegateExp *)aggr)->func->isNested())
|
||||
// See Bugzilla 3560
|
||||
e = new CallExp(loc, ((DelegateExp *)aggr)->e1, exps);
|
||||
else
|
||||
e = new CallExp(loc, aggr, exps);
|
||||
e = e->semantic(sc);
|
||||
if (e->type != Type::tint32)
|
||||
error("opApply() function for %s must return an int", tab->toChars());
|
||||
@@ -3888,10 +3893,12 @@ Statement *WithStatement::semantic(Scope *sc)
|
||||
else if (exp->op == TOKtype)
|
||||
{ TypeExp *es = (TypeExp *)exp;
|
||||
|
||||
sym = es->type->toDsymbol(sc)->isScopeDsymbol();
|
||||
Dsymbol *s = es->type->toDsymbol(sc);
|
||||
sym = s ? s->isScopeDsymbol() : NULL;
|
||||
if (!sym)
|
||||
{ error("%s has no members", es->toChars());
|
||||
body = body->semantic(sc);
|
||||
{ error("with type %s has no members", es->toChars());
|
||||
if (body)
|
||||
body = body->semantic(sc);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -4454,8 +4461,8 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
|
||||
this->enclosingFinally = NULL;
|
||||
this->enclosingScopeExit = NULL;
|
||||
this->lblock = NULL;
|
||||
this->isReturnLabel = 0;
|
||||
this->asmLabel = false;
|
||||
this->fwdrefs = NULL;
|
||||
}
|
||||
|
||||
Statement *LabelStatement::syntaxCopy()
|
||||
|
||||
+2
-1
@@ -853,7 +853,8 @@ struct LabelStatement : Statement
|
||||
TryFinallyStatement *enclosingFinally;
|
||||
Statement* enclosingScopeExit;
|
||||
block *lblock; // back end
|
||||
int isReturnLabel;
|
||||
|
||||
Array *fwdrefs; // forward references to this LabelStatement
|
||||
|
||||
LabelStatement(Loc loc, Identifier *ident, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
|
||||
Reference in New Issue
Block a user