mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
Merged DMD 1.042.
This commit is contained in:
25
dmd/attrib.c
25
dmd/attrib.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -322,7 +322,7 @@ void StorageClassDeclaration::semantic(Scope *sc)
|
||||
sc->stc = stc;
|
||||
}
|
||||
|
||||
void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
|
||||
{
|
||||
struct SCstring
|
||||
{
|
||||
@@ -350,18 +350,19 @@ void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
// { STCtls, TOKtls },
|
||||
};
|
||||
|
||||
int written = 0;
|
||||
for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
|
||||
{
|
||||
if (stc & table[i].stc)
|
||||
{
|
||||
if (written)
|
||||
buf->writeByte(' ');
|
||||
written = 1;
|
||||
buf->writestring(Token::toChars(table[i].tok));
|
||||
buf->writeByte(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
stcToCBuffer(buf, stc);
|
||||
AttribDeclaration::toCBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
@@ -1193,6 +1194,18 @@ void PragmaDeclaration::toObjFile(int multiobj)
|
||||
name[se->len] = 0;
|
||||
obj_includelib(name);
|
||||
}
|
||||
#if DMDV2
|
||||
else if (ident == Id::startaddress)
|
||||
{
|
||||
assert(args && args->dim == 1);
|
||||
Expression *e = (Expression *)args->data[0];
|
||||
Dsymbol *sa = getDsymbol(e);
|
||||
FuncDeclaration *f = sa->isFuncDeclaration();
|
||||
assert(f);
|
||||
Symbol *s = f->toSymbol();
|
||||
obj_startaddress(s);
|
||||
}
|
||||
#endif
|
||||
AttribDeclaration::toObjFile(multiobj);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -68,6 +68,8 @@ struct StorageClassDeclaration: AttribDeclaration
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
static void stcToCBuffer(OutBuffer *buf, int stc);
|
||||
};
|
||||
|
||||
struct LinkDeclaration : AttribDeclaration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -228,7 +228,7 @@ MATCH IntegerExp::implicitConvTo(Type *t)
|
||||
|
||||
case Tchar:
|
||||
case Tuns8:
|
||||
//printf("value = %llu %llu\n", (integer_t)(unsigned char)value, value);
|
||||
//printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
|
||||
if ((unsigned char)value != value)
|
||||
goto Lno;
|
||||
goto Lyes;
|
||||
|
||||
@@ -562,7 +562,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
// sc->offset += PTRSIZE; // room for uplevel context pointer
|
||||
}
|
||||
else
|
||||
{ sc->offset = 2*PTRSIZE; // allow room for vptr[] and monitor
|
||||
{ sc->offset = PTRSIZE * 2; // allow room for vptr[] and monitor
|
||||
alignsize = PTRSIZE;
|
||||
}
|
||||
structsize = sc->offset;
|
||||
@@ -1152,7 +1152,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
sc->linkage = LINKwindows;
|
||||
sc->structalign = 8;
|
||||
structalign = sc->structalign;
|
||||
sc->offset = 2*PTRSIZE;
|
||||
sc->offset = PTRSIZE * 2;
|
||||
inuse++;
|
||||
for (i = 0; i < members->dim; i++)
|
||||
{
|
||||
|
||||
@@ -129,7 +129,14 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
|
||||
{
|
||||
"DigitalMars", "X86", "X86_64",
|
||||
"Windows", "Win32", "Win64",
|
||||
"linux", "Posix", "OSX", "FreeBSD",
|
||||
"linux",
|
||||
#if DMDV2
|
||||
/* Although Posix is predefined by D1, disallowing its
|
||||
* redefinition breaks makefiles and older builds.
|
||||
*/
|
||||
"Posix",
|
||||
#endif
|
||||
"OSX", "FreeBSD",
|
||||
"LittleEndian", "BigEndian",
|
||||
"all",
|
||||
"none",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -555,7 +555,7 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
Loc loc = e1->loc;
|
||||
unsigned count;
|
||||
integer_t value;
|
||||
dinteger_t value;
|
||||
|
||||
value = e1->toInteger();
|
||||
count = e2->toInteger();
|
||||
@@ -604,7 +604,7 @@ Expression *Ushr(Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
Loc loc = e1->loc;
|
||||
unsigned count;
|
||||
integer_t value;
|
||||
dinteger_t value;
|
||||
|
||||
value = e1->toInteger();
|
||||
count = e2->toInteger();
|
||||
@@ -887,7 +887,7 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
Loc loc = e1->loc;
|
||||
integer_t n;
|
||||
dinteger_t n;
|
||||
real_t r1;
|
||||
real_t r2;
|
||||
|
||||
@@ -1058,7 +1058,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
||||
else if (type->isintegral())
|
||||
{
|
||||
if (e1->type->isfloating())
|
||||
{ integer_t result;
|
||||
{ dinteger_t result;
|
||||
real_t r = e1->toReal();
|
||||
|
||||
switch (type->toBasetype()->ty)
|
||||
@@ -1251,7 +1251,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
|
||||
if (iupr > es1->len || ilwr > iupr)
|
||||
e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
|
||||
else
|
||||
{ integer_t value;
|
||||
{ dinteger_t value;
|
||||
void *s;
|
||||
size_t len = iupr - ilwr;
|
||||
int sz = es1->sz;
|
||||
@@ -1317,7 +1317,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
StringExp *es;
|
||||
size_t len = 1;
|
||||
int sz = tn->size();
|
||||
integer_t v = e->toInteger();
|
||||
dinteger_t v = e->toInteger();
|
||||
|
||||
s = mem.malloc((len + 1) * sz);
|
||||
memcpy((unsigned char *)s, &v, sz);
|
||||
@@ -1384,7 +1384,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
Type *t;
|
||||
size_t len = es1->len + 1;
|
||||
int sz = es1->sz;
|
||||
integer_t v = e2->toInteger();
|
||||
dinteger_t v = e2->toInteger();
|
||||
|
||||
s = mem.malloc((len + 1) * sz);
|
||||
memcpy(s, es1->string, es1->len * sz);
|
||||
@@ -1409,7 +1409,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
Type *t;
|
||||
size_t len = 1 + es2->len;
|
||||
int sz = es2->sz;
|
||||
integer_t v = e1->toInteger();
|
||||
dinteger_t v = e1->toInteger();
|
||||
|
||||
s = mem.malloc((len + 1) * sz);
|
||||
memcpy((unsigned char *)s, &v, sz);
|
||||
|
||||
2842
dmd/declaration.c
2842
dmd/declaration.c
File diff suppressed because it is too large
Load Diff
1828
dmd/declaration.h
1828
dmd/declaration.h
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
@@ -32,9 +32,9 @@ struct EnumDeclaration : ScopeDsymbol
|
||||
Type *memtype; // type of the members
|
||||
|
||||
#if DMDV1
|
||||
integer_t maxval;
|
||||
integer_t minval;
|
||||
integer_t defaultval; // default initializer
|
||||
dinteger_t maxval;
|
||||
dinteger_t minval;
|
||||
dinteger_t defaultval; // default initializer
|
||||
#else
|
||||
Expression *maxval;
|
||||
Expression *minval;
|
||||
|
||||
@@ -34,15 +34,6 @@ int isnan(double);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
// Issues with using -include total.h (defines integer_t) and then complex.h fails...
|
||||
#undef integer_t
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
|
||||
#include "rmem.h"
|
||||
|
||||
//#include "port.h"
|
||||
@@ -700,7 +691,6 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
arg = arg->checkToPointer();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DMDV2
|
||||
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
|
||||
{
|
||||
@@ -1000,7 +990,7 @@ Expression *Expression::combine(Expression *e1, Expression *e2)
|
||||
return e1;
|
||||
}
|
||||
|
||||
integer_t Expression::toInteger()
|
||||
dinteger_t Expression::toInteger()
|
||||
{
|
||||
//printf("Expression %s\n", Token::toChars(op));
|
||||
error("Integer constant expression expected instead of %s", toChars());
|
||||
@@ -1289,7 +1279,7 @@ Expressions *Expression::arraySyntaxCopy(Expressions *exps)
|
||||
|
||||
/******************************** IntegerExp **************************/
|
||||
|
||||
IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
|
||||
IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
|
||||
: Expression(loc, TOKint64, sizeof(IntegerExp))
|
||||
{
|
||||
//printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
|
||||
@@ -1303,7 +1293,7 @@ IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
IntegerExp::IntegerExp(integer_t value)
|
||||
IntegerExp::IntegerExp(dinteger_t value)
|
||||
: Expression(0, TOKint64, sizeof(IntegerExp))
|
||||
{
|
||||
this->type = Type::tint32;
|
||||
@@ -1333,7 +1323,7 @@ char *IntegerExp::toChars()
|
||||
#endif
|
||||
}
|
||||
|
||||
integer_t IntegerExp::toInteger()
|
||||
dinteger_t IntegerExp::toInteger()
|
||||
{ Type *t;
|
||||
|
||||
t = type;
|
||||
@@ -1355,11 +1345,12 @@ integer_t IntegerExp::toInteger()
|
||||
case Tint64: value = (d_int64) value; break;
|
||||
case Tuns64: value = (d_uns64) value; break;
|
||||
case Tpointer:
|
||||
// FIXME: Other pointer widths than 32 and 64?
|
||||
if (PTRSIZE == 4)
|
||||
value = (d_uns32) value;
|
||||
else
|
||||
else if (PTRSIZE == 8)
|
||||
value = (d_uns64) value;
|
||||
else
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case Tenum:
|
||||
@@ -1423,7 +1414,7 @@ Expression *IntegerExp::semantic(Scope *sc)
|
||||
if (!type)
|
||||
{
|
||||
// Determine what the type of this number is
|
||||
integer_t number = value;
|
||||
dinteger_t number = value;
|
||||
|
||||
if (number & 0x8000000000000000LL)
|
||||
type = Type::tuns64;
|
||||
@@ -1451,7 +1442,7 @@ Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
|
||||
|
||||
void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
integer_t v = toInteger();
|
||||
dinteger_t v = toInteger();
|
||||
|
||||
if (type)
|
||||
{ Type *t = type;
|
||||
@@ -1520,7 +1511,7 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
break;
|
||||
|
||||
case Tuns64:
|
||||
L4:
|
||||
L4:
|
||||
buf->printf("%juLU", v);
|
||||
break;
|
||||
|
||||
@@ -1533,11 +1524,12 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writestring("cast(");
|
||||
buf->writestring(t->toChars());
|
||||
buf->writeByte(')');
|
||||
// FIXME: Other pointer widths than 32 and 64?
|
||||
if (PTRSIZE == 4)
|
||||
goto L3;
|
||||
else
|
||||
else if (PTRSIZE == 8)
|
||||
goto L4;
|
||||
else
|
||||
assert(0);
|
||||
|
||||
default:
|
||||
/* This can happen if errors, such as
|
||||
@@ -1592,7 +1584,7 @@ char *RealExp::toChars()
|
||||
return mem.strdup(buffer);
|
||||
}
|
||||
|
||||
integer_t RealExp::toInteger()
|
||||
dinteger_t RealExp::toInteger()
|
||||
{
|
||||
#ifdef IN_GCC
|
||||
return toReal().toInt();
|
||||
@@ -1817,7 +1809,7 @@ char *ComplexExp::toChars()
|
||||
return mem.strdup(buffer);
|
||||
}
|
||||
|
||||
integer_t ComplexExp::toInteger()
|
||||
dinteger_t ComplexExp::toInteger()
|
||||
{
|
||||
#ifdef IN_GCC
|
||||
return (sinteger_t) toReal().toInt();
|
||||
@@ -2163,9 +2155,11 @@ Lagain:
|
||||
imp = s->isImport();
|
||||
if (imp)
|
||||
{
|
||||
ScopeExp *ie;
|
||||
|
||||
ie = new ScopeExp(loc, imp->pkg);
|
||||
if (!imp->pkg)
|
||||
{ error("forward reference of import %s", imp->toChars());
|
||||
return this;
|
||||
}
|
||||
ScopeExp *ie = new ScopeExp(loc, imp->pkg);
|
||||
return ie->semantic(sc);
|
||||
}
|
||||
pkg = s->isPackage();
|
||||
@@ -3650,7 +3644,7 @@ Lagain:
|
||||
|
||||
if (cd->aggNew)
|
||||
{
|
||||
// Prepend the size_t size argument to newargs[]
|
||||
// Prepend the size argument to newargs[]
|
||||
Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
|
||||
if (!newargs)
|
||||
newargs = new Expressions();
|
||||
@@ -4319,7 +4313,8 @@ char *FuncExp::toChars()
|
||||
|
||||
void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring(fd->toChars());
|
||||
fd->toCBuffer(buf, hgs);
|
||||
//buf->writestring(fd->toChars());
|
||||
}
|
||||
|
||||
|
||||
@@ -7593,8 +7588,8 @@ Expression *IndexExp::semantic(Scope *sc)
|
||||
e2 = e2->optimize(WANTvalue);
|
||||
if (e2->op == TOKint64)
|
||||
{
|
||||
integer_t index = e2->toInteger();
|
||||
integer_t length = tsa->dim->toInteger();
|
||||
dinteger_t index = e2->toInteger();
|
||||
dinteger_t length = tsa->dim->toInteger();
|
||||
if (index < 0 || index >= length)
|
||||
error("array index [%lld] is outside array bounds [0 .. %lld]",
|
||||
index, length);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -105,7 +105,7 @@ struct Expression : Object
|
||||
static Expression *combine(Expression *e1, Expression *e2);
|
||||
static Expressions *arraySyntaxCopy(Expressions *exps);
|
||||
|
||||
virtual integer_t toInteger();
|
||||
virtual dinteger_t toInteger();
|
||||
virtual uinteger_t toUInteger();
|
||||
virtual real_t toReal();
|
||||
virtual real_t toImaginary();
|
||||
@@ -175,16 +175,16 @@ struct Expression : Object
|
||||
|
||||
struct IntegerExp : Expression
|
||||
{
|
||||
integer_t value;
|
||||
dinteger_t value;
|
||||
|
||||
IntegerExp(Loc loc, integer_t value, Type *type);
|
||||
IntegerExp(integer_t value);
|
||||
IntegerExp(Loc loc, dinteger_t value, Type *type);
|
||||
IntegerExp(dinteger_t value);
|
||||
int equals(Object *o);
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
char *toChars();
|
||||
void dump(int indent);
|
||||
integer_t toInteger();
|
||||
dinteger_t toInteger();
|
||||
real_t toReal();
|
||||
real_t toImaginary();
|
||||
complex_t toComplex();
|
||||
@@ -212,7 +212,7 @@ struct RealExp : Expression
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
char *toChars();
|
||||
integer_t toInteger();
|
||||
dinteger_t toInteger();
|
||||
uinteger_t toUInteger();
|
||||
real_t toReal();
|
||||
real_t toImaginary();
|
||||
@@ -240,7 +240,7 @@ struct ComplexExp : Expression
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
char *toChars();
|
||||
integer_t toInteger();
|
||||
dinteger_t toInteger();
|
||||
uinteger_t toUInteger();
|
||||
real_t toReal();
|
||||
real_t toImaginary();
|
||||
|
||||
@@ -1237,7 +1237,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
{ // Call invariant virtually
|
||||
ThisExp *v = new ThisExp(0);
|
||||
v->type = vthis->type;
|
||||
Expression *se = new StringExp(0, "null this");
|
||||
Expression *se = new StringExp(0, (char *)"null this");
|
||||
se = se->semantic(sc);
|
||||
se->type = Type::tchar->arrayOf();
|
||||
e = new AssertExp(loc, v, se);
|
||||
@@ -2878,7 +2878,7 @@ void NewDeclaration::semantic(Scope *sc)
|
||||
type = type->semantic(loc, sc);
|
||||
assert(type->ty == Tfunction);
|
||||
|
||||
// Check that there is at least one argument of type uint
|
||||
// Check that there is at least one argument of type size_t
|
||||
TypeFunction *tf = (TypeFunction *)type;
|
||||
if (Argument::dim(tf->parameters) < 1)
|
||||
{
|
||||
|
||||
@@ -45,9 +45,9 @@ char *Identifier::toChars()
|
||||
return (char *)string;
|
||||
}
|
||||
|
||||
char *Identifier::toHChars2()
|
||||
const char *Identifier::toHChars2()
|
||||
{
|
||||
char *p = NULL;
|
||||
const char *p = NULL;
|
||||
|
||||
if (this == Id::ctor) p = "this";
|
||||
else if (this == Id::dtor) p = "~this";
|
||||
|
||||
@@ -37,7 +37,7 @@ struct Identifier : Object
|
||||
#ifdef _DH
|
||||
char *toHChars();
|
||||
#endif
|
||||
char *toHChars2();
|
||||
const char *toHChars2();
|
||||
int dyncast();
|
||||
|
||||
static Identifier *generateId(const char *prefix);
|
||||
|
||||
34
dmd/lexer.c
34
dmd/lexer.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -8,7 +8,7 @@
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#define __C99FEATURES__ 1
|
||||
#include <cmath>
|
||||
|
||||
/* Lexical Analyzer */
|
||||
|
||||
@@ -20,19 +20,7 @@
|
||||
#include <wchar.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#if _MSC_VER
|
||||
#include <time.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include <time.h>
|
||||
#elif __GNUC__
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <time.h> // for time() and ctime()
|
||||
|
||||
#include "rmem.h"
|
||||
|
||||
@@ -49,10 +37,6 @@
|
||||
extern "C" char * __cdecl __locale_decpoint;
|
||||
#endif
|
||||
|
||||
#if _MSC_VER // workaround VC++ bug, labels and types should be in separate namespaces
|
||||
#define Lstring Lstr
|
||||
#endif
|
||||
|
||||
extern int HtmlNamedEntity(unsigned char *p, int length);
|
||||
|
||||
#define LS 0x2028 // UTF line separator
|
||||
@@ -682,7 +666,7 @@ void Lexer::scan(Token *t)
|
||||
if (mod && id == Id::FILE)
|
||||
{
|
||||
t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars());
|
||||
goto Lstring;
|
||||
goto Lstr;
|
||||
}
|
||||
else if (mod && id == Id::LINE)
|
||||
{
|
||||
@@ -694,22 +678,22 @@ void Lexer::scan(Token *t)
|
||||
if (id == Id::DATE)
|
||||
{
|
||||
t->ustring = (unsigned char *)date;
|
||||
goto Lstring;
|
||||
goto Lstr;
|
||||
}
|
||||
else if (id == Id::TIME)
|
||||
{
|
||||
t->ustring = (unsigned char *)time;
|
||||
goto Lstring;
|
||||
goto Lstr;
|
||||
}
|
||||
else if (id == Id::VENDOR)
|
||||
{
|
||||
t->ustring = (unsigned char *)"LDC";
|
||||
goto Lstring;
|
||||
goto Lstr;
|
||||
}
|
||||
else if (id == Id::TIMESTAMP)
|
||||
{
|
||||
t->ustring = (unsigned char *)timestamp;
|
||||
Lstring:
|
||||
Lstr:
|
||||
t->value = TOKstring;
|
||||
Llen:
|
||||
t->postfix = 0;
|
||||
@@ -3097,4 +3081,6 @@ void Lexer::initKeywords()
|
||||
Token::tochars[TOKdeclaration] = "declaration";
|
||||
Token::tochars[TOKdottd] = "dottd";
|
||||
Token::tochars[TOKon_scope_exit] = "scope(exit)";
|
||||
Token::tochars[TOKon_scope_success] = "scope(success)";
|
||||
Token::tochars[TOKon_scope_failure] = "scope(failure)";
|
||||
}
|
||||
|
||||
610
dmd/lexer.h
610
dmd/lexer.h
@@ -1,305 +1,305 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 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_LEXER_H
|
||||
#define DMD_LEXER_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "mars.h"
|
||||
|
||||
struct StringTable;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
|
||||
/* Tokens:
|
||||
( )
|
||||
[ ]
|
||||
{ }
|
||||
< > <= >= == != === !==
|
||||
<< >> <<= >>= >>> >>>=
|
||||
+ - += -=
|
||||
* / % *= /= %=
|
||||
& | ^ &= |= ^=
|
||||
= ! ~
|
||||
++ --
|
||||
. -> : ,
|
||||
? && ||
|
||||
*/
|
||||
|
||||
enum TOK
|
||||
{
|
||||
TOKreserved,
|
||||
|
||||
// Other
|
||||
TOKlparen, TOKrparen,
|
||||
TOKlbracket, TOKrbracket,
|
||||
TOKlcurly, TOKrcurly,
|
||||
TOKcolon, TOKneg,
|
||||
TOKsemicolon, TOKdotdotdot,
|
||||
TOKeof, TOKcast,
|
||||
TOKnull, TOKassert,
|
||||
TOKtrue, TOKfalse,
|
||||
TOKarray, TOKcall,
|
||||
TOKaddress, TOKtypedot,
|
||||
TOKtype, TOKthrow,
|
||||
TOKnew, TOKdelete,
|
||||
TOKstar, TOKsymoff,
|
||||
TOKvar, TOKdotvar,
|
||||
TOKdotti, TOKdotexp,
|
||||
TOKdottype, TOKslice,
|
||||
TOKarraylength, TOKversion,
|
||||
TOKmodule, TOKdollar,
|
||||
TOKtemplate, TOKdottd,
|
||||
TOKdeclaration, TOKtypeof,
|
||||
TOKpragma, TOKdsymbol,
|
||||
TOKtypeid, TOKuadd,
|
||||
TOKremove,
|
||||
TOKnewanonclass, TOKcomment,
|
||||
TOKarrayliteral, TOKassocarrayliteral,
|
||||
TOKstructliteral,
|
||||
|
||||
// Operators
|
||||
TOKlt, TOKgt,
|
||||
TOKle, TOKge,
|
||||
TOKequal, TOKnotequal,
|
||||
TOKidentity, TOKnotidentity,
|
||||
TOKindex, TOKis,
|
||||
TOKtobool,
|
||||
|
||||
// 60
|
||||
// NCEG floating point compares
|
||||
// !<>= <> <>= !> !>= !< !<= !<>
|
||||
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
|
||||
|
||||
TOKshl, TOKshr,
|
||||
TOKshlass, TOKshrass,
|
||||
TOKushr, TOKushrass,
|
||||
TOKcat, TOKcatass, // ~ ~=
|
||||
TOKadd, TOKmin, TOKaddass, TOKminass,
|
||||
TOKmul, TOKdiv, TOKmod,
|
||||
TOKmulass, TOKdivass, TOKmodass,
|
||||
TOKand, TOKor, TOKxor,
|
||||
TOKandass, TOKorass, TOKxorass,
|
||||
TOKassign, TOKnot, TOKtilde,
|
||||
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
|
||||
TOKdot, TOKarrow, TOKcomma,
|
||||
TOKquestion, TOKandand, TOKoror,
|
||||
|
||||
// 104
|
||||
// Numeric literals
|
||||
TOKint32v, TOKuns32v,
|
||||
TOKint64v, TOKuns64v,
|
||||
TOKfloat32v, TOKfloat64v, TOKfloat80v,
|
||||
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
|
||||
|
||||
// Char constants
|
||||
TOKcharv, TOKwcharv, TOKdcharv,
|
||||
|
||||
// Leaf operators
|
||||
TOKidentifier, TOKstring,
|
||||
TOKthis, TOKsuper,
|
||||
TOKhalt, TOKtuple,
|
||||
|
||||
// Basic types
|
||||
TOKvoid,
|
||||
TOKint8, TOKuns8,
|
||||
TOKint16, TOKuns16,
|
||||
TOKint32, TOKuns32,
|
||||
TOKint64, TOKuns64,
|
||||
TOKfloat32, TOKfloat64, TOKfloat80,
|
||||
TOKimaginary32, TOKimaginary64, TOKimaginary80,
|
||||
TOKcomplex32, TOKcomplex64, TOKcomplex80,
|
||||
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
|
||||
TOKcent, TOKucent,
|
||||
|
||||
// Aggregates
|
||||
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
|
||||
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
|
||||
TOKmixin,
|
||||
|
||||
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
|
||||
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
|
||||
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
|
||||
TOKauto, TOKpackage, TOKmanifest,
|
||||
|
||||
// Statements
|
||||
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
|
||||
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
|
||||
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
|
||||
TOKasm, TOKforeach, TOKforeach_reverse,
|
||||
TOKscope,
|
||||
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
|
||||
|
||||
// Contracts
|
||||
TOKbody, TOKinvariant,
|
||||
|
||||
// Testing
|
||||
TOKunittest,
|
||||
|
||||
// Added after 1.0
|
||||
TOKref,
|
||||
TOKmacro,
|
||||
#if DMDV2
|
||||
TOKtraits,
|
||||
TOKoverloadset,
|
||||
TOKpure,
|
||||
TOKnothrow,
|
||||
TOKtls,
|
||||
TOKline,
|
||||
TOKfile,
|
||||
TOKshared,
|
||||
#endif
|
||||
|
||||
// LDC specific
|
||||
#if IN_LLVM
|
||||
TOKgep,
|
||||
#endif
|
||||
|
||||
TOKMAX
|
||||
};
|
||||
|
||||
#define CASE_BASIC_TYPES \
|
||||
case TOKwchar: case TOKdchar: \
|
||||
case TOKbit: case TOKbool: case TOKchar: \
|
||||
case TOKint8: case TOKuns8: \
|
||||
case TOKint16: case TOKuns16: \
|
||||
case TOKint32: case TOKuns32: \
|
||||
case TOKint64: case TOKuns64: \
|
||||
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
|
||||
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
|
||||
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
|
||||
case TOKvoid
|
||||
|
||||
#define CASE_BASIC_TYPES_X(t) \
|
||||
case TOKvoid: t = Type::tvoid; goto LabelX; \
|
||||
case TOKint8: t = Type::tint8; goto LabelX; \
|
||||
case TOKuns8: t = Type::tuns8; goto LabelX; \
|
||||
case TOKint16: t = Type::tint16; goto LabelX; \
|
||||
case TOKuns16: t = Type::tuns16; goto LabelX; \
|
||||
case TOKint32: t = Type::tint32; goto LabelX; \
|
||||
case TOKuns32: t = Type::tuns32; goto LabelX; \
|
||||
case TOKint64: t = Type::tint64; goto LabelX; \
|
||||
case TOKuns64: t = Type::tuns64; goto LabelX; \
|
||||
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
|
||||
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
|
||||
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
|
||||
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
|
||||
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
|
||||
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
|
||||
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
|
||||
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
|
||||
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
|
||||
case TOKbit: t = Type::tbit; goto LabelX; \
|
||||
case TOKbool: t = Type::tbool; goto LabelX; \
|
||||
case TOKchar: t = Type::tchar; goto LabelX; \
|
||||
case TOKwchar: t = Type::twchar; goto LabelX; \
|
||||
case TOKdchar: t = Type::tdchar; goto LabelX; \
|
||||
LabelX
|
||||
|
||||
struct Token
|
||||
{
|
||||
Token *next;
|
||||
unsigned char *ptr; // pointer to first character of this token within buffer
|
||||
enum TOK value;
|
||||
unsigned char *blockComment; // doc comment string prior to this token
|
||||
unsigned char *lineComment; // doc comment for previous token
|
||||
union
|
||||
{
|
||||
// Integers
|
||||
d_int64 int64value;
|
||||
d_uns64 uns64value;
|
||||
|
||||
// Floats
|
||||
#ifdef IN_GCC
|
||||
// real_t float80value; // can't use this in a union!
|
||||
#else
|
||||
d_float80 float80value;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{ unsigned char *ustring; // UTF8 string
|
||||
unsigned len;
|
||||
unsigned char postfix; // 'c', 'w', 'd'
|
||||
};
|
||||
|
||||
Identifier *ident;
|
||||
};
|
||||
#ifdef IN_GCC
|
||||
real_t float80value; // can't use this in a union!
|
||||
#endif
|
||||
|
||||
static const char *tochars[TOKMAX];
|
||||
static void *operator new(size_t sz);
|
||||
|
||||
int isKeyword();
|
||||
void print();
|
||||
const char *toChars();
|
||||
static const char *toChars(enum TOK);
|
||||
};
|
||||
|
||||
struct Lexer
|
||||
{
|
||||
static StringTable stringtable;
|
||||
static OutBuffer stringbuffer;
|
||||
static Token *freelist;
|
||||
|
||||
Loc loc; // for error messages
|
||||
|
||||
unsigned char *base; // pointer to start of buffer
|
||||
unsigned char *end; // past end of buffer
|
||||
unsigned char *p; // current character
|
||||
Token token;
|
||||
Module *mod;
|
||||
int doDocComment; // collect doc comment information
|
||||
int anyToken; // !=0 means seen at least one token
|
||||
int commentToken; // !=0 means comments are TOKcomment's
|
||||
|
||||
Lexer(Module *mod,
|
||||
unsigned char *base, unsigned begoffset, unsigned endoffset,
|
||||
int doDocComment, int commentToken);
|
||||
|
||||
static void initKeywords();
|
||||
static Identifier *idPool(const char *s);
|
||||
static Identifier *uniqueId(const char *s);
|
||||
static Identifier *uniqueId(const char *s, int num);
|
||||
|
||||
TOK nextToken();
|
||||
TOK peekNext();
|
||||
void scan(Token *t);
|
||||
Token *peek(Token *t);
|
||||
Token *peekPastParen(Token *t);
|
||||
unsigned escapeSequence();
|
||||
TOK wysiwygStringConstant(Token *t, int tc);
|
||||
TOK hexStringConstant(Token *t);
|
||||
#if DMDV2
|
||||
TOK delimitedStringConstant(Token *t);
|
||||
TOK tokenStringConstant(Token *t);
|
||||
#endif
|
||||
TOK escapeStringConstant(Token *t, int wide);
|
||||
TOK charConstant(Token *t, int wide);
|
||||
void stringPostfix(Token *t);
|
||||
unsigned wchar(unsigned u);
|
||||
TOK number(Token *t);
|
||||
TOK inreal(Token *t);
|
||||
void error(const char *format, ...);
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void pragma();
|
||||
unsigned decodeUTF();
|
||||
void getDocComment(Token *t, unsigned lineComment);
|
||||
|
||||
static int isValidIdentifier(char *p);
|
||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||
};
|
||||
|
||||
#endif /* DMD_LEXER_H */
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 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_LEXER_H
|
||||
#define DMD_LEXER_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include "root.h"
|
||||
#include "mars.h"
|
||||
|
||||
struct StringTable;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
|
||||
/* Tokens:
|
||||
( )
|
||||
[ ]
|
||||
{ }
|
||||
< > <= >= == != === !==
|
||||
<< >> <<= >>= >>> >>>=
|
||||
+ - += -=
|
||||
* / % *= /= %=
|
||||
& | ^ &= |= ^=
|
||||
= ! ~
|
||||
++ --
|
||||
. -> : ,
|
||||
? && ||
|
||||
*/
|
||||
|
||||
enum TOK
|
||||
{
|
||||
TOKreserved,
|
||||
|
||||
// Other
|
||||
TOKlparen, TOKrparen,
|
||||
TOKlbracket, TOKrbracket,
|
||||
TOKlcurly, TOKrcurly,
|
||||
TOKcolon, TOKneg,
|
||||
TOKsemicolon, TOKdotdotdot,
|
||||
TOKeof, TOKcast,
|
||||
TOKnull, TOKassert,
|
||||
TOKtrue, TOKfalse,
|
||||
TOKarray, TOKcall,
|
||||
TOKaddress, TOKtypedot,
|
||||
TOKtype, TOKthrow,
|
||||
TOKnew, TOKdelete,
|
||||
TOKstar, TOKsymoff,
|
||||
TOKvar, TOKdotvar,
|
||||
TOKdotti, TOKdotexp,
|
||||
TOKdottype, TOKslice,
|
||||
TOKarraylength, TOKversion,
|
||||
TOKmodule, TOKdollar,
|
||||
TOKtemplate, TOKdottd,
|
||||
TOKdeclaration, TOKtypeof,
|
||||
TOKpragma, TOKdsymbol,
|
||||
TOKtypeid, TOKuadd,
|
||||
TOKremove,
|
||||
TOKnewanonclass, TOKcomment,
|
||||
TOKarrayliteral, TOKassocarrayliteral,
|
||||
TOKstructliteral,
|
||||
|
||||
// Operators
|
||||
TOKlt, TOKgt,
|
||||
TOKle, TOKge,
|
||||
TOKequal, TOKnotequal,
|
||||
TOKidentity, TOKnotidentity,
|
||||
TOKindex, TOKis,
|
||||
TOKtobool,
|
||||
|
||||
// 60
|
||||
// NCEG floating point compares
|
||||
// !<>= <> <>= !> !>= !< !<= !<>
|
||||
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
|
||||
|
||||
TOKshl, TOKshr,
|
||||
TOKshlass, TOKshrass,
|
||||
TOKushr, TOKushrass,
|
||||
TOKcat, TOKcatass, // ~ ~=
|
||||
TOKadd, TOKmin, TOKaddass, TOKminass,
|
||||
TOKmul, TOKdiv, TOKmod,
|
||||
TOKmulass, TOKdivass, TOKmodass,
|
||||
TOKand, TOKor, TOKxor,
|
||||
TOKandass, TOKorass, TOKxorass,
|
||||
TOKassign, TOKnot, TOKtilde,
|
||||
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
|
||||
TOKdot, TOKarrow, TOKcomma,
|
||||
TOKquestion, TOKandand, TOKoror,
|
||||
|
||||
// 104
|
||||
// Numeric literals
|
||||
TOKint32v, TOKuns32v,
|
||||
TOKint64v, TOKuns64v,
|
||||
TOKfloat32v, TOKfloat64v, TOKfloat80v,
|
||||
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
|
||||
|
||||
// Char constants
|
||||
TOKcharv, TOKwcharv, TOKdcharv,
|
||||
|
||||
// Leaf operators
|
||||
TOKidentifier, TOKstring,
|
||||
TOKthis, TOKsuper,
|
||||
TOKhalt, TOKtuple,
|
||||
|
||||
// Basic types
|
||||
TOKvoid,
|
||||
TOKint8, TOKuns8,
|
||||
TOKint16, TOKuns16,
|
||||
TOKint32, TOKuns32,
|
||||
TOKint64, TOKuns64,
|
||||
TOKfloat32, TOKfloat64, TOKfloat80,
|
||||
TOKimaginary32, TOKimaginary64, TOKimaginary80,
|
||||
TOKcomplex32, TOKcomplex64, TOKcomplex80,
|
||||
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
|
||||
TOKcent, TOKucent,
|
||||
|
||||
// Aggregates
|
||||
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
|
||||
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
|
||||
TOKmixin,
|
||||
|
||||
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
|
||||
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
|
||||
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
|
||||
TOKauto, TOKpackage, TOKmanifest,
|
||||
|
||||
// Statements
|
||||
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
|
||||
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
|
||||
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
|
||||
TOKasm, TOKforeach, TOKforeach_reverse,
|
||||
TOKscope,
|
||||
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
|
||||
|
||||
// Contracts
|
||||
TOKbody, TOKinvariant,
|
||||
|
||||
// Testing
|
||||
TOKunittest,
|
||||
|
||||
// Added after 1.0
|
||||
TOKref,
|
||||
TOKmacro,
|
||||
#if DMDV2
|
||||
TOKtraits,
|
||||
TOKoverloadset,
|
||||
TOKpure,
|
||||
TOKnothrow,
|
||||
TOKtls,
|
||||
TOKline,
|
||||
TOKfile,
|
||||
TOKshared,
|
||||
#endif
|
||||
|
||||
// LDC specific
|
||||
#if IN_LLVM
|
||||
TOKgep,
|
||||
#endif
|
||||
|
||||
TOKMAX
|
||||
};
|
||||
|
||||
#define CASE_BASIC_TYPES \
|
||||
case TOKwchar: case TOKdchar: \
|
||||
case TOKbit: case TOKbool: case TOKchar: \
|
||||
case TOKint8: case TOKuns8: \
|
||||
case TOKint16: case TOKuns16: \
|
||||
case TOKint32: case TOKuns32: \
|
||||
case TOKint64: case TOKuns64: \
|
||||
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
|
||||
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
|
||||
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
|
||||
case TOKvoid
|
||||
|
||||
#define CASE_BASIC_TYPES_X(t) \
|
||||
case TOKvoid: t = Type::tvoid; goto LabelX; \
|
||||
case TOKint8: t = Type::tint8; goto LabelX; \
|
||||
case TOKuns8: t = Type::tuns8; goto LabelX; \
|
||||
case TOKint16: t = Type::tint16; goto LabelX; \
|
||||
case TOKuns16: t = Type::tuns16; goto LabelX; \
|
||||
case TOKint32: t = Type::tint32; goto LabelX; \
|
||||
case TOKuns32: t = Type::tuns32; goto LabelX; \
|
||||
case TOKint64: t = Type::tint64; goto LabelX; \
|
||||
case TOKuns64: t = Type::tuns64; goto LabelX; \
|
||||
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
|
||||
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
|
||||
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
|
||||
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
|
||||
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
|
||||
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
|
||||
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
|
||||
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
|
||||
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
|
||||
case TOKbit: t = Type::tbit; goto LabelX; \
|
||||
case TOKbool: t = Type::tbool; goto LabelX; \
|
||||
case TOKchar: t = Type::tchar; goto LabelX; \
|
||||
case TOKwchar: t = Type::twchar; goto LabelX; \
|
||||
case TOKdchar: t = Type::tdchar; goto LabelX; \
|
||||
LabelX
|
||||
|
||||
struct Token
|
||||
{
|
||||
Token *next;
|
||||
unsigned char *ptr; // pointer to first character of this token within buffer
|
||||
enum TOK value;
|
||||
unsigned char *blockComment; // doc comment string prior to this token
|
||||
unsigned char *lineComment; // doc comment for previous token
|
||||
union
|
||||
{
|
||||
// Integers
|
||||
d_int64 int64value;
|
||||
d_uns64 uns64value;
|
||||
|
||||
// Floats
|
||||
#ifdef IN_GCC
|
||||
// real_t float80value; // can't use this in a union!
|
||||
#else
|
||||
d_float80 float80value;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{ unsigned char *ustring; // UTF8 string
|
||||
unsigned len;
|
||||
unsigned char postfix; // 'c', 'w', 'd'
|
||||
};
|
||||
|
||||
Identifier *ident;
|
||||
};
|
||||
#ifdef IN_GCC
|
||||
real_t float80value; // can't use this in a union!
|
||||
#endif
|
||||
|
||||
static const char *tochars[TOKMAX];
|
||||
static void *operator new(size_t sz);
|
||||
|
||||
int isKeyword();
|
||||
void print();
|
||||
const char *toChars();
|
||||
static const char *toChars(enum TOK);
|
||||
};
|
||||
|
||||
struct Lexer
|
||||
{
|
||||
static StringTable stringtable;
|
||||
static OutBuffer stringbuffer;
|
||||
static Token *freelist;
|
||||
|
||||
Loc loc; // for error messages
|
||||
|
||||
unsigned char *base; // pointer to start of buffer
|
||||
unsigned char *end; // past end of buffer
|
||||
unsigned char *p; // current character
|
||||
Token token;
|
||||
Module *mod;
|
||||
int doDocComment; // collect doc comment information
|
||||
int anyToken; // !=0 means seen at least one token
|
||||
int commentToken; // !=0 means comments are TOKcomment's
|
||||
|
||||
Lexer(Module *mod,
|
||||
unsigned char *base, unsigned begoffset, unsigned endoffset,
|
||||
int doDocComment, int commentToken);
|
||||
|
||||
static void initKeywords();
|
||||
static Identifier *idPool(const char *s);
|
||||
static Identifier *uniqueId(const char *s);
|
||||
static Identifier *uniqueId(const char *s, int num);
|
||||
|
||||
TOK nextToken();
|
||||
TOK peekNext();
|
||||
void scan(Token *t);
|
||||
Token *peek(Token *t);
|
||||
Token *peekPastParen(Token *t);
|
||||
unsigned escapeSequence();
|
||||
TOK wysiwygStringConstant(Token *t, int tc);
|
||||
TOK hexStringConstant(Token *t);
|
||||
#if DMDV2
|
||||
TOK delimitedStringConstant(Token *t);
|
||||
TOK tokenStringConstant(Token *t);
|
||||
#endif
|
||||
TOK escapeStringConstant(Token *t, int wide);
|
||||
TOK charConstant(Token *t, int wide);
|
||||
void stringPostfix(Token *t);
|
||||
unsigned wchar(unsigned u);
|
||||
TOK number(Token *t);
|
||||
TOK inreal(Token *t);
|
||||
void error(const char *format, ...);
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void pragma();
|
||||
unsigned decodeUTF();
|
||||
void getDocComment(Token *t, unsigned lineComment);
|
||||
|
||||
static int isValidIdentifier(char *p);
|
||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||
};
|
||||
|
||||
#endif /* DMD_LEXER_H */
|
||||
|
||||
@@ -117,7 +117,7 @@ char *Declaration::mangle()
|
||||
return ident->toChars();
|
||||
|
||||
case LINKcpp:
|
||||
#if V2 && (TARGET_LINUX || TARGET_OSX)
|
||||
#if DMDV2 && (TARGET_LINUX || TARGET_OSX)
|
||||
return cpp_mangle(this);
|
||||
#else
|
||||
// Windows C++ mangling is done by C++ back end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
@@ -15,10 +16,6 @@
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
|
||||
#if __DMC__
|
||||
#include <dos.h>
|
||||
#endif
|
||||
|
||||
#if POSIX
|
||||
#include <errno.h>
|
||||
#elif _WIN32
|
||||
@@ -59,7 +56,7 @@ Global::Global()
|
||||
|
||||
copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
version = "v1.041";
|
||||
version = "v1.042";
|
||||
ldc_version = LDC_REV;
|
||||
llvm_version = LLVM_REV_STR;
|
||||
global.structalign = 8;
|
||||
|
||||
16
dmd/mars.h
16
dmd/mars.h
@@ -57,6 +57,7 @@ the target object file format:
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
@@ -77,7 +78,8 @@ the target object file format:
|
||||
|
||||
#define DMDV2 0 // Version 2.0 features
|
||||
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
|
||||
#define STRUCTTHISREF V2 // if 'this' for struct is a reference, not a pointer
|
||||
#define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer
|
||||
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
|
||||
|
||||
/* Other targets are TARGET_LINUX and TARGET_OSX, which are
|
||||
* set on the command line via the compiler makefile.
|
||||
@@ -261,11 +263,6 @@ extern Global global;
|
||||
#define WINDOWS_SEH (_WIN32 && __DMC__)
|
||||
|
||||
|
||||
#if __GNUC__
|
||||
//#define memicmp strncasecmp
|
||||
//#define stricmp strcasecmp
|
||||
#endif
|
||||
|
||||
#ifdef __DMC__
|
||||
typedef _Complex long double complex_t;
|
||||
#else
|
||||
@@ -274,12 +271,13 @@ extern Global global;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Be careful not to care about sign when using integer_t
|
||||
typedef uint64_t integer_t;
|
||||
// Be careful not to care about sign when using dinteger_t
|
||||
//typedef uint64_t integer_t;
|
||||
typedef uint64_t dinteger_t; // use this instead of integer_t to
|
||||
// avoid conflicts with system #include's
|
||||
|
||||
// Signed and unsigned variants
|
||||
typedef int64_t sinteger_t;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
|
||||
69
dmd/mtype.c
69
dmd/mtype.c
@@ -25,10 +25,6 @@
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef __DMC__
|
||||
#include <fp.h>
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
#include <malloc.h>
|
||||
#include <complex>
|
||||
@@ -37,19 +33,10 @@
|
||||
#include <complex.h>
|
||||
#elif __MINGW32__
|
||||
#include <malloc.h>
|
||||
#else
|
||||
//#define signbit 56
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
#if !(defined (__SVR4) && defined (__sun))
|
||||
#include <bits/nan.h>
|
||||
#include <bits/mathdef.h>
|
||||
#endif
|
||||
#endif
|
||||
static double zero = 0;
|
||||
|
||||
#include "rmem.h"
|
||||
#include "port.h"
|
||||
|
||||
#include "dsymbol.h"
|
||||
#include "mtype.h"
|
||||
@@ -85,15 +72,18 @@ FuncDeclaration *hasThis(Scope *sc);
|
||||
*/
|
||||
|
||||
int PTRSIZE = 4;
|
||||
#if IN_LLVM
|
||||
int REALSIZE = 8;
|
||||
int REALPAD = 0;
|
||||
#elif TARGET_LINUX
|
||||
#if TARGET_OSX
|
||||
int REALSIZE = 16;
|
||||
int REALPAD = 6;
|
||||
int REALALIGNSIZE = 16;
|
||||
#elif TARGET_LINUX || TARGET_FREEBSD
|
||||
int REALSIZE = 12;
|
||||
int REALPAD = 2;
|
||||
int REALALIGNSIZE = 4;
|
||||
#else
|
||||
int REALSIZE = 10;
|
||||
int REALPAD = 0;
|
||||
int REALALIGNSIZE = 2;
|
||||
#endif
|
||||
int Tsize_t = Tuns32;
|
||||
int Tptrdiff_t = Tint32;
|
||||
@@ -1119,24 +1109,7 @@ Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
|
||||
case Tfloat64:
|
||||
case Tfloat80:
|
||||
{
|
||||
#if IN_GCC
|
||||
// mode doesn't matter, will be converted in RealExp anyway
|
||||
fvalue = real_t::getnan(real_t::LongDouble);
|
||||
#elif __GNUC__
|
||||
// gcc nan's have the sign bit set by default, so turn it off
|
||||
// Need the volatile to prevent gcc from doing incorrect
|
||||
// constant folding.
|
||||
volatile d_float80 foo;
|
||||
foo = NAN;
|
||||
if (std::signbit(foo)) // signbit sometimes, not always, set
|
||||
foo = -foo; // turn off sign bit
|
||||
fvalue = foo;
|
||||
#elif _MSC_VER
|
||||
unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
|
||||
fvalue = *(double*)nan;
|
||||
#else
|
||||
fvalue = NAN;
|
||||
#endif
|
||||
fvalue = Port::nan;
|
||||
goto Lfvalue;
|
||||
}
|
||||
}
|
||||
@@ -1154,15 +1127,7 @@ Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
|
||||
case Tfloat32:
|
||||
case Tfloat64:
|
||||
case Tfloat80:
|
||||
#if IN_GCC
|
||||
fvalue = real_t::getinfinity();
|
||||
#elif __GNUC__
|
||||
fvalue = 1 / zero;
|
||||
#elif _MSC_VER
|
||||
fvalue = std::numeric_limits<long double>::infinity();
|
||||
#else
|
||||
fvalue = INFINITY;
|
||||
#endif
|
||||
fvalue = Port::infinity;
|
||||
goto Lfvalue;
|
||||
}
|
||||
}
|
||||
@@ -1378,7 +1343,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
||||
}
|
||||
|
||||
Expression *TypeBasic::defaultInit(Loc loc)
|
||||
{ integer_t value = 0;
|
||||
{ dinteger_t value = 0;
|
||||
|
||||
#if LOGDEFAULTINIT
|
||||
printf("TypeBasic::defaultInit() '%s'\n", toChars());
|
||||
@@ -1735,7 +1700,7 @@ Type *TypeSArray::syntaxCopy()
|
||||
}
|
||||
|
||||
d_uns64 TypeSArray::size(Loc loc)
|
||||
{ integer_t sz;
|
||||
{ dinteger_t sz;
|
||||
|
||||
if (!dim)
|
||||
return Type::size(loc);
|
||||
@@ -1747,7 +1712,7 @@ d_uns64 TypeSArray::size(Loc loc)
|
||||
sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords
|
||||
}
|
||||
else
|
||||
{ integer_t n, n2;
|
||||
{ dinteger_t n, n2;
|
||||
|
||||
n = next->size();
|
||||
n2 = n * sz;
|
||||
@@ -1896,7 +1861,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
Type *tbn = next->toBasetype();
|
||||
|
||||
if (dim)
|
||||
{ integer_t n, n2;
|
||||
{ dinteger_t n, n2;
|
||||
|
||||
dim = semanticLength(sc, tbn, dim);
|
||||
|
||||
@@ -1909,10 +1874,10 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
*/
|
||||
return this;
|
||||
}
|
||||
integer_t d1 = dim->toInteger();
|
||||
dinteger_t d1 = dim->toInteger();
|
||||
dim = dim->castTo(sc, tsize_t);
|
||||
dim = dim->optimize(WANTvalue);
|
||||
integer_t d2 = dim->toInteger();
|
||||
dinteger_t d2 = dim->toInteger();
|
||||
|
||||
if (d1 != d2)
|
||||
goto Loverflow;
|
||||
@@ -3052,7 +3017,7 @@ int TypeFunction::callMatch(Expressions *args)
|
||||
if (varargs == 2 && u + 1 == nparams) // if last varargs param
|
||||
{ Type *tb = p->type->toBasetype();
|
||||
TypeSArray *tsa;
|
||||
integer_t sz;
|
||||
dinteger_t sz;
|
||||
|
||||
switch (tb->ty)
|
||||
{
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
#include <complex>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define integer_t dmd_integer_t
|
||||
#endif
|
||||
|
||||
#include "rmem.h"
|
||||
|
||||
//#include "port.h"
|
||||
|
||||
1582
dmd/optimize.c
1582
dmd/optimize.c
File diff suppressed because it is too large
Load Diff
189
dmd/parse.c
189
dmd/parse.c
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -32,6 +32,9 @@
|
||||
#include "enum.h"
|
||||
#include "id.h"
|
||||
#include "version.h"
|
||||
#if DMDV2
|
||||
#include "aliasthis.h"
|
||||
#endif
|
||||
|
||||
// How multiple declarations are parsed.
|
||||
// If 1, treat as C.
|
||||
@@ -75,6 +78,25 @@ Array *Parser::parseModule()
|
||||
unsigned char *comment = token.blockComment;
|
||||
|
||||
nextToken();
|
||||
#if DMDV2
|
||||
if (token.value == TOKlparen)
|
||||
{
|
||||
nextToken();
|
||||
if (token.value != TOKidentifier)
|
||||
{ error("module (system) identifier expected");
|
||||
goto Lerr;
|
||||
}
|
||||
Identifier *id = token.ident;
|
||||
|
||||
if (id == Id::system)
|
||||
safe = TRUE;
|
||||
else
|
||||
error("(safe) expected, not %s", id->toChars());
|
||||
nextToken();
|
||||
check(TOKrparen);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (token.value != TOKidentifier)
|
||||
{ error("Identifier expected following module");
|
||||
goto Lerr;
|
||||
@@ -259,6 +281,13 @@ Array *Parser::parseDeclDefs(int once)
|
||||
case TOKabstract: stc = STCabstract; goto Lstc;
|
||||
case TOKsynchronized: stc = STCsynchronized; goto Lstc;
|
||||
case TOKdeprecated: stc = STCdeprecated; goto Lstc;
|
||||
#if DMDV2
|
||||
case TOKnothrow: stc = STCnothrow; goto Lstc;
|
||||
case TOKpure: stc = STCpure; goto Lstc;
|
||||
case TOKref: stc = STCref; goto Lstc;
|
||||
case TOKtls: stc = STCtls; goto Lstc;
|
||||
//case TOKmanifest: stc = STCmanifest; goto Lstc;
|
||||
#endif
|
||||
|
||||
Lstc:
|
||||
nextToken();
|
||||
@@ -342,6 +371,16 @@ Array *Parser::parseDeclDefs(int once)
|
||||
|
||||
Lprot:
|
||||
nextToken();
|
||||
switch (token.value)
|
||||
{
|
||||
case TOKprivate:
|
||||
case TOKpackage:
|
||||
case TOKprotected:
|
||||
case TOKpublic:
|
||||
case TOKexport:
|
||||
error("redundant protection attribute");
|
||||
break;
|
||||
}
|
||||
a = parseBlock();
|
||||
s = new ProtDeclaration(prot, a);
|
||||
break;
|
||||
@@ -802,7 +841,7 @@ StaticDtorDeclaration *Parser::parseStaticDtor()
|
||||
|
||||
/*****************************************
|
||||
* Parse an invariant definition:
|
||||
* invariant { body }
|
||||
* invariant() { body }
|
||||
* Current token is 'invariant'.
|
||||
*/
|
||||
|
||||
@@ -987,7 +1026,7 @@ Arguments *Parser::parseParameters(int *pvarargs)
|
||||
EnumDeclaration *Parser::parseEnum()
|
||||
{ EnumDeclaration *e;
|
||||
Identifier *id;
|
||||
Type *t;
|
||||
Type *memtype;
|
||||
Loc loc = this->loc;
|
||||
|
||||
//printf("Parser::parseEnum()\n");
|
||||
@@ -1002,12 +1041,12 @@ EnumDeclaration *Parser::parseEnum()
|
||||
if (token.value == TOKcolon)
|
||||
{
|
||||
nextToken();
|
||||
t = parseBasicType();
|
||||
memtype = parseBasicType();
|
||||
}
|
||||
else
|
||||
t = NULL;
|
||||
memtype = NULL;
|
||||
|
||||
e = new EnumDeclaration(loc, id, t);
|
||||
e = new EnumDeclaration(loc, id, memtype);
|
||||
if (token.value == TOKsemicolon && id)
|
||||
nextToken();
|
||||
else if (token.value == TOKlcurly)
|
||||
@@ -1058,6 +1097,10 @@ EnumDeclaration *Parser::parseEnum()
|
||||
return e;
|
||||
}
|
||||
|
||||
/********************************
|
||||
* Parse struct, union, interface, class.
|
||||
*/
|
||||
|
||||
Dsymbol *Parser::parseAggregate()
|
||||
{ AggregateDeclaration *a = NULL;
|
||||
int anon = 0;
|
||||
@@ -1160,7 +1203,7 @@ Dsymbol *Parser::parseAggregate()
|
||||
// Wrap a template around the aggregate declaration
|
||||
decldefs = new Array();
|
||||
decldefs->push(a);
|
||||
tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
|
||||
tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
|
||||
return tempdecl;
|
||||
}
|
||||
|
||||
@@ -1265,7 +1308,7 @@ TemplateDeclaration *Parser::parseTemplateDeclaration()
|
||||
nextToken();
|
||||
}
|
||||
|
||||
tempdecl = new TemplateDeclaration(loc, id, tpl, decldefs);
|
||||
tempdecl = new TemplateDeclaration(loc, id, tpl, NULL, decldefs);
|
||||
return tempdecl;
|
||||
|
||||
Lerr:
|
||||
@@ -1650,6 +1693,60 @@ Import *Parser::parseImport(Array *decldefs, int isstatic)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl)
|
||||
{ Type *t;
|
||||
|
||||
/* Take care of the storage class prefixes that
|
||||
* serve as type attributes:
|
||||
* const shared, shared const, const, invariant, shared
|
||||
*/
|
||||
if (token.value == TOKconst && peekNext() == TOKshared && peekNext2() != TOKlparen ||
|
||||
token.value == TOKshared && peekNext() == TOKconst && peekNext2() != TOKlparen)
|
||||
{
|
||||
nextToken();
|
||||
nextToken();
|
||||
/* shared const type
|
||||
*/
|
||||
t = parseType(pident, tpl);
|
||||
t = t->makeSharedConst();
|
||||
return t;
|
||||
}
|
||||
else if (token.value == TOKconst && peekNext() != TOKlparen)
|
||||
{
|
||||
nextToken();
|
||||
/* const type
|
||||
*/
|
||||
t = parseType(pident, tpl);
|
||||
t = t->makeConst();
|
||||
return t;
|
||||
}
|
||||
else if ((token.value == TOKinvariant || token.value == TOKimmutable) &&
|
||||
peekNext() != TOKlparen)
|
||||
{
|
||||
nextToken();
|
||||
/* invariant type
|
||||
*/
|
||||
t = parseType(pident, tpl);
|
||||
t = t->makeInvariant();
|
||||
return t;
|
||||
}
|
||||
else if (token.value == TOKshared && peekNext() != TOKlparen)
|
||||
{
|
||||
nextToken();
|
||||
/* shared type
|
||||
*/
|
||||
t = parseType(pident, tpl);
|
||||
t = t->makeShared();
|
||||
return t;
|
||||
}
|
||||
else
|
||||
t = parseBasicType();
|
||||
t = parseDeclarator(t, pident, tpl);
|
||||
return t;
|
||||
}
|
||||
#endif
|
||||
|
||||
Type *Parser::parseBasicType()
|
||||
{ Type *t;
|
||||
Identifier *id;
|
||||
@@ -1889,6 +1986,7 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters *
|
||||
break;
|
||||
}
|
||||
|
||||
// parse DeclaratorSuffixes
|
||||
while (1)
|
||||
{
|
||||
switch (token.value)
|
||||
@@ -1924,6 +2022,7 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters *
|
||||
ta = new TypeSArray(t, e);
|
||||
check(TOKrbracket);
|
||||
}
|
||||
|
||||
/* Insert ta into
|
||||
* ts -> ... -> t
|
||||
* so that
|
||||
@@ -1986,7 +2085,7 @@ Array *Parser::parseDeclarations()
|
||||
Type *tfirst;
|
||||
Identifier *ident;
|
||||
Array *a;
|
||||
enum TOK tok;
|
||||
enum TOK tok = TOKreserved;
|
||||
unsigned char *comment = token.blockComment;
|
||||
enum LINK link = linkage;
|
||||
|
||||
@@ -2018,6 +2117,13 @@ Array *Parser::parseDeclarations()
|
||||
case TOKabstract: stc = STCabstract; goto L1;
|
||||
case TOKsynchronized: stc = STCsynchronized; goto L1;
|
||||
case TOKdeprecated: stc = STCdeprecated; goto L1;
|
||||
#if DMDV2
|
||||
case TOKnothrow: stc = STCnothrow; goto L1;
|
||||
case TOKpure: stc = STCpure; goto L1;
|
||||
case TOKref: stc = STCref; goto L1;
|
||||
case TOKtls: stc = STCtls; goto L1;
|
||||
case TOKenum: stc = STCmanifest; goto L1;
|
||||
#endif
|
||||
L1:
|
||||
if (storage_class & stc)
|
||||
error("redundant storage class '%s'", token.toChars());
|
||||
@@ -2108,9 +2214,8 @@ Array *Parser::parseDeclarations()
|
||||
|
||||
if (tok == TOKtypedef || tok == TOKalias)
|
||||
{ Declaration *v;
|
||||
Initializer *init;
|
||||
Initializer *init = NULL;
|
||||
|
||||
init = NULL;
|
||||
if (token.value == TOKassign)
|
||||
{
|
||||
nextToken();
|
||||
@@ -2150,13 +2255,12 @@ Array *Parser::parseDeclarations()
|
||||
}
|
||||
}
|
||||
else if (t->ty == Tfunction)
|
||||
{ FuncDeclaration *f;
|
||||
Dsymbol *s;
|
||||
|
||||
f = new FuncDeclaration(loc, 0, ident, storage_class, t);
|
||||
{ FuncDeclaration *f =
|
||||
new FuncDeclaration(loc, 0, ident, storage_class, t);
|
||||
addComment(f, comment);
|
||||
parseContracts(f);
|
||||
addComment(f, NULL);
|
||||
Dsymbol *s;
|
||||
if (link == linkage)
|
||||
{
|
||||
s = f;
|
||||
@@ -2174,23 +2278,22 @@ Array *Parser::parseDeclarations()
|
||||
// Wrap a template around the aggregate declaration
|
||||
decldefs = new Array();
|
||||
decldefs->push(s);
|
||||
tempdecl = new TemplateDeclaration(loc, s->ident, tpl, decldefs);
|
||||
tempdecl = new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs);
|
||||
s = tempdecl;
|
||||
}
|
||||
addComment(s, comment);
|
||||
a->push(s);
|
||||
}
|
||||
else
|
||||
{ VarDeclaration *v;
|
||||
Initializer *init;
|
||||
|
||||
init = NULL;
|
||||
{
|
||||
Initializer *init = NULL;
|
||||
if (token.value == TOKassign)
|
||||
{
|
||||
nextToken();
|
||||
init = parseInitializer();
|
||||
}
|
||||
v = new VarDeclaration(loc, t, ident, init);
|
||||
|
||||
VarDeclaration *v = new VarDeclaration(loc, t, ident, init);
|
||||
v->storage_class = storage_class;
|
||||
if (link == linkage)
|
||||
a->push(v);
|
||||
@@ -2363,6 +2466,7 @@ L1:
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Parse initializer for variable declaration.
|
||||
*/
|
||||
|
||||
Initializer *Parser::parseInitializer()
|
||||
@@ -2620,13 +2724,14 @@ Statement *Parser::parseStatement(int flags)
|
||||
switch (token.value)
|
||||
{
|
||||
case TOKidentifier:
|
||||
// Need to look ahead to see if it is a declaration, label, or expression
|
||||
/* A leading identifier can be a declaration, label, or expression.
|
||||
* The easiest case to check first is label:
|
||||
*/
|
||||
t = peek(&token);
|
||||
if (t->value == TOKcolon)
|
||||
{ // It's a label
|
||||
Identifier *ident;
|
||||
|
||||
ident = token.ident;
|
||||
Identifier *ident = token.ident;
|
||||
nextToken();
|
||||
nextToken();
|
||||
s = parseStatement(PSsemi);
|
||||
@@ -2718,6 +2823,10 @@ Statement *Parser::parseStatement(int flags)
|
||||
case TOKextern:
|
||||
case TOKfinal:
|
||||
case TOKinvariant:
|
||||
#if DMDV2
|
||||
case TOKimmutable:
|
||||
case TOKshared:
|
||||
#endif
|
||||
// case TOKtypeof:
|
||||
Ldeclaration:
|
||||
{ Array *a;
|
||||
@@ -2733,7 +2842,7 @@ Statement *Parser::parseStatement(int flags)
|
||||
s = new DeclarationStatement(loc, d);
|
||||
as->push(s);
|
||||
}
|
||||
s = new CompoundStatement(loc, as);
|
||||
s = new CompoundDeclarationStatement(loc, as);
|
||||
}
|
||||
else if (a->dim == 1)
|
||||
{
|
||||
@@ -3443,7 +3552,7 @@ void Parser::check(Loc loc, enum TOK value)
|
||||
nextToken();
|
||||
}
|
||||
|
||||
void Parser::check(enum TOK value, char *string)
|
||||
void Parser::check(enum TOK value, const char *string)
|
||||
{
|
||||
if (token.value != value)
|
||||
error("found '%s' when expecting '%s' following '%s'",
|
||||
@@ -3461,6 +3570,7 @@ void Parser::check(enum TOK value, char *string)
|
||||
|
||||
int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
|
||||
{
|
||||
//printf("isDeclaration(needId = %d)\n", needId);
|
||||
int haveId = 0;
|
||||
|
||||
#if DMDV2
|
||||
@@ -3551,9 +3661,11 @@ int Parser::isBasicType(Token **pt)
|
||||
goto Lfalse;
|
||||
}
|
||||
*pt = t;
|
||||
//printf("is\n");
|
||||
return TRUE;
|
||||
|
||||
Lfalse:
|
||||
//printf("is not\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -3678,6 +3790,25 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
|
||||
parens = FALSE;
|
||||
if (!isParameters(&t))
|
||||
return FALSE;
|
||||
#if DMDV2
|
||||
while (1)
|
||||
{
|
||||
switch (t->value)
|
||||
{
|
||||
case TOKconst:
|
||||
case TOKinvariant:
|
||||
case TOKimmutable:
|
||||
case TOKshared:
|
||||
case TOKpure:
|
||||
case TOKnothrow:
|
||||
t = peek(t);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
|
||||
// Valid tokens that follow a declaration
|
||||
@@ -4203,6 +4334,12 @@ Expression *Parser::parsePrimaryExp()
|
||||
token.value == TOKsuper ||
|
||||
token.value == TOKenum ||
|
||||
token.value == TOKinterface ||
|
||||
#if DMDV2
|
||||
token.value == TOKconst && peek(&token)->value == TOKrparen ||
|
||||
token.value == TOKinvariant && peek(&token)->value == TOKrparen ||
|
||||
token.value == TOKimmutable && peek(&token)->value == TOKrparen ||
|
||||
token.value == TOKshared && peek(&token)->value == TOKrparen ||
|
||||
#endif
|
||||
token.value == TOKfunction ||
|
||||
token.value == TOKdelegate ||
|
||||
token.value == TOKreturn))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -100,7 +100,7 @@ struct Parser : Lexer
|
||||
Initializer *parseInitializer();
|
||||
void check(Loc loc, enum TOK value);
|
||||
void check(enum TOK value);
|
||||
void check(enum TOK value, char *string);
|
||||
void check(enum TOK value, const char *string);
|
||||
int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt);
|
||||
int isBasicType(Token **pt);
|
||||
int isDeclarator(Token **pt, int *haveId, enum TOK endtok);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2006 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
|
||||
177
dmd/root/async.c
Normal file
177
dmd/root/async.c
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
#define _MT 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <process.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
static unsigned __stdcall startthread(void *p);
|
||||
|
||||
struct FileData
|
||||
{
|
||||
File *file;
|
||||
int result;
|
||||
HANDLE event;
|
||||
};
|
||||
|
||||
struct AsyncRead
|
||||
{
|
||||
static AsyncRead *create(size_t nfiles);
|
||||
void addFile(File *file);
|
||||
void start();
|
||||
int read(size_t i);
|
||||
static void dispose(AsyncRead *);
|
||||
|
||||
HANDLE hThread;
|
||||
|
||||
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);
|
||||
files[filesdim].file = file;
|
||||
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
ResetEvent(files[filesdim].event);
|
||||
filesdim++;
|
||||
}
|
||||
|
||||
void AsyncRead::start()
|
||||
{
|
||||
unsigned threadaddr;
|
||||
hThread = (HANDLE) _beginthreadex(NULL,
|
||||
0,
|
||||
&startthread,
|
||||
this,
|
||||
0,
|
||||
(unsigned *)&threadaddr);
|
||||
|
||||
if (hThread)
|
||||
{
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
int AsyncRead::read(size_t i)
|
||||
{
|
||||
FileData *f = &files[i];
|
||||
WaitForSingleObject(f->event, INFINITE);
|
||||
Sleep(0); // give up time slice
|
||||
return f->result;
|
||||
}
|
||||
|
||||
void AsyncRead::dispose(AsyncRead *aw)
|
||||
{
|
||||
delete aw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned __stdcall startthread(void *p)
|
||||
{
|
||||
AsyncRead *aw = (AsyncRead *)p;
|
||||
|
||||
for (size_t i = 0; i < aw->filesdim; i++)
|
||||
{ FileData *f = &aw->files[i];
|
||||
|
||||
f->result = f->file->read();
|
||||
SetEvent(f->event);
|
||||
}
|
||||
_endthreadex(EXIT_SUCCESS);
|
||||
return EXIT_SUCCESS; // if skidding
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
struct FileData
|
||||
{
|
||||
File *file;
|
||||
int result;
|
||||
//HANDLE event;
|
||||
};
|
||||
|
||||
struct AsyncRead
|
||||
{
|
||||
static AsyncRead *create(size_t nfiles);
|
||||
void addFile(File *file);
|
||||
void start();
|
||||
int read(size_t i);
|
||||
static void dispose(AsyncRead *);
|
||||
|
||||
//HANDLE hThread;
|
||||
|
||||
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);
|
||||
files[filesdim].file = file;
|
||||
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
//ResetEvent(files[filesdim].event);
|
||||
filesdim++;
|
||||
}
|
||||
|
||||
void AsyncRead::start()
|
||||
{
|
||||
}
|
||||
|
||||
int AsyncRead::read(size_t i)
|
||||
{
|
||||
FileData *f = &files[i];
|
||||
f->result = f->file->read();
|
||||
return f->result;
|
||||
}
|
||||
|
||||
void AsyncRead::dispose(AsyncRead *aw)
|
||||
{
|
||||
delete aw;
|
||||
}
|
||||
|
||||
#endif
|
||||
33
dmd/root/async.h
Normal file
33
dmd/root/async.h
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
// Copyright (c) 2009-2009 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 ASYNC_H
|
||||
#define ASYNC_H
|
||||
|
||||
#if __DMC__
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
/*******************
|
||||
* Simple interface to read files asynchronously in another
|
||||
* thread.
|
||||
*/
|
||||
|
||||
struct AsyncRead
|
||||
{
|
||||
static AsyncRead *create(size_t nfiles);
|
||||
void addFile(File *file);
|
||||
void start();
|
||||
int read(size_t i);
|
||||
static void dispose(AsyncRead *);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
754
dmd/root/port.c
Normal file
754
dmd/root/port.c
Normal file
@@ -0,0 +1,754 @@
|
||||
|
||||
// Copyright (c) 1999-2009 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>
|
||||
#include <fp.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = INFINITY;
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return ::isnan(r);
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
return ::isnan(r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::isfinite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::fpclassify(r) == FP_INFINITE);
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return ::signbit(r);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
return ::strupr(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
// Disable useless warnings about unreferenced functions
|
||||
#pragma warning (disable : 4514)
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
|
||||
//static unsigned long nanarray[2] = {0,0x7FF80000 };
|
||||
double Port::nan = (*(double *)nanarray);
|
||||
|
||||
//static unsigned long infinityarray[2] = {0,0x7FF00000 };
|
||||
static double zero = 0;
|
||||
double Port::infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
Port::infinity = std::numeric_limits<long double>::infinity();
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return ::_isnan(r);
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
return ::_isnan(r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* MSVC doesn't have 80 bit long doubles
|
||||
*/
|
||||
return isSignallingNan((double) r);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::_finite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&(r))[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
if (y == 0)
|
||||
return 1; // even if x is NAN
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
unsigned _int64 number = 0;
|
||||
int c;
|
||||
int error;
|
||||
#define ULLONG_MAX ((unsigned _int64)~0I64)
|
||||
|
||||
while (isspace(*p)) /* skip leading white space */
|
||||
p++;
|
||||
if (*p == '+')
|
||||
p++;
|
||||
switch (base)
|
||||
{ case 0:
|
||||
base = 10; /* assume decimal base */
|
||||
if (*p == '0')
|
||||
{ base = 8; /* could be octal */
|
||||
p++;
|
||||
switch (*p)
|
||||
{ case 'x':
|
||||
case 'X':
|
||||
base = 16; /* hex */
|
||||
p++;
|
||||
break;
|
||||
#if BINARY
|
||||
case 'b':
|
||||
case 'B':
|
||||
base = 2; /* binary */
|
||||
p++;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16: /* skip over '0x' and '0X' */
|
||||
if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
|
||||
p += 2;
|
||||
break;
|
||||
#if BINARY
|
||||
case 2: /* skip over '0b' and '0B' */
|
||||
if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
|
||||
p += 2;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
error = 0;
|
||||
for (;;)
|
||||
{ c = *p;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c = (c & ~0x20) - ('A' - 10);
|
||||
else /* unrecognized character */
|
||||
break;
|
||||
if (c >= base) /* not in number base */
|
||||
break;
|
||||
if ((ULLONG_MAX - c) / base < number)
|
||||
error = 1;
|
||||
number = number * base + c;
|
||||
p++;
|
||||
}
|
||||
if (pend)
|
||||
*pend = (char *)p;
|
||||
if (error)
|
||||
{ number = ULLONG_MAX;
|
||||
errno = ERANGE;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64toa(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64tow(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{ double d;
|
||||
|
||||
if ((__int64) ull < 0)
|
||||
{
|
||||
// MSVC doesn't implement the conversion
|
||||
d = (double) (__int64)(ull - 0x8000000000000000i64);
|
||||
d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
|
||||
}
|
||||
else
|
||||
d = (double)(__int64)ull;
|
||||
return d;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
return ::strupr(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__
|
||||
|
||||
#include <math.h>
|
||||
#if linux
|
||||
#include <bits/nan.h>
|
||||
#include <bits/mathdef.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
// gcc nan's have the sign bit set by default, so turn it off
|
||||
// Need the volatile to prevent gcc from doing incorrect
|
||||
// constant folding.
|
||||
volatile long double foo;
|
||||
foo = NAN;
|
||||
if (signbit(foo)) // signbit sometimes, not always, set
|
||||
foo = -foo; // turn off sign bit
|
||||
Port::nan = foo;
|
||||
}
|
||||
|
||||
#undef isnan
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::finite(r);
|
||||
}
|
||||
|
||||
#undef isinf
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return fpclassify(r) == FP_INFINITE;
|
||||
#else
|
||||
return ::isinf(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (__SVR4) && defined (__sun)
|
||||
|
||||
#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
// gcc nan's have the sign bit set by default, so turn it off
|
||||
// Need the volatile to prevent gcc from doing incorrect
|
||||
// constant folding.
|
||||
volatile long double foo;
|
||||
foo = NAN;
|
||||
if (signbit(foo)) // signbit sometimes, not always, set
|
||||
foo = -foo; // turn off sign bit
|
||||
Port::nan = foo;
|
||||
}
|
||||
|
||||
#undef isnan
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::finite(r);
|
||||
}
|
||||
|
||||
#undef isinf
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return ::isinf(r);
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
|
||||
#include <math.h>
|
||||
#include <bits/nan.h>
|
||||
#include <bits/mathdef.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
|
||||
#include "d-gcc-real.h"
|
||||
extern "C" bool real_isnan (const real_t *);
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
Port::infinity = real_t::getinfinity();
|
||||
Port::nan = real_t::getnan(real_t::LongDouble);
|
||||
}
|
||||
|
||||
#undef isnan
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
return __inline_isnan(r);
|
||||
#else
|
||||
return ::isnan(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Port::isNan(long double r)
|
||||
{
|
||||
return real_isnan(&r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(long double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::finite(r);
|
||||
}
|
||||
|
||||
#undef isinf
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return ::isinf(r);
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
// Copyright (c) 1999-2002 by Digital Mars
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// http://www.digitalmars.com
|
||||
|
||||
#ifndef PORT_H
|
||||
#define PORT_H
|
||||
@@ -42,6 +42,11 @@ struct Port
|
||||
#undef signbit
|
||||
#endif
|
||||
static int isNan(double);
|
||||
static int isNan(long double);
|
||||
|
||||
static int isSignallingNan(double);
|
||||
static int isSignallingNan(long double);
|
||||
|
||||
static int isFinite(double);
|
||||
static int isInfinity(double);
|
||||
static int Signbit(double);
|
||||
@@ -58,8 +63,10 @@ struct Port
|
||||
static double ull_to_double(ulonglong ull);
|
||||
|
||||
// Get locale-dependent list separator
|
||||
static char *list_separator();
|
||||
static wchar_t *wlist_separator();
|
||||
static const char *list_separator();
|
||||
static const wchar_t *wlist_separator();
|
||||
|
||||
static char *strupr(char *);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -583,9 +583,17 @@ char *FileName::name(const char *str)
|
||||
return e + 1;
|
||||
|
||||
#if _WIN32
|
||||
case '/':
|
||||
case '\\':
|
||||
case ':':
|
||||
return e + 1;
|
||||
case ':':
|
||||
/* The ':' is a drive letter only if it is the second
|
||||
* character or the last character,
|
||||
* otherwise it is an ADS (Alternate Data Stream) separator.
|
||||
* Consider ADS separators as part of the file name.
|
||||
*/
|
||||
if (e == str + 1 || e == str + len - 1)
|
||||
return e + 1;
|
||||
#endif
|
||||
default:
|
||||
if (e == str)
|
||||
@@ -620,7 +628,7 @@ char *FileName::path(const char *str)
|
||||
n--;
|
||||
|
||||
#if _WIN32
|
||||
if (n[-1] == '\\')
|
||||
if (n[-1] == '\\' || n[-1] == '/')
|
||||
n--;
|
||||
#endif
|
||||
}
|
||||
@@ -822,8 +830,8 @@ void FileName::ensurePathExists(const char *path)
|
||||
if (*p)
|
||||
{
|
||||
#if _WIN32
|
||||
size_t len = strlen(p);
|
||||
if (len > 2 && p[-1] == ':')
|
||||
size_t len = strlen(path);
|
||||
if (len > 2 && p[-1] == ':' && path + 2 == p)
|
||||
{ mem.free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
234
dmd/scope.h
234
dmd/scope.h
@@ -1,114 +1,120 @@
|
||||
|
||||
// Copyright (c) 1999-2005 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_SCOPE_H
|
||||
#define DMD_SCOPE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
struct Dsymbol;
|
||||
struct ScopeDsymbol;
|
||||
struct Array;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
struct Statement;
|
||||
struct SwitchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct LabelStatement;
|
||||
struct ForeachStatement;
|
||||
struct ClassDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct AnonymousAggregateDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct DocComment;
|
||||
struct EnclosingHandler;
|
||||
struct AnonDeclaration;
|
||||
enum LINK;
|
||||
enum PROT;
|
||||
|
||||
struct Scope
|
||||
{
|
||||
Scope *enclosing; // enclosing Scope
|
||||
|
||||
Module *module; // Root module
|
||||
ScopeDsymbol *scopesym; // current symbol
|
||||
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
|
||||
// sd gets the addMember()
|
||||
FuncDeclaration *func; // function we are in
|
||||
Dsymbol *parent; // parent to use
|
||||
LabelStatement *slabel; // enclosing labelled statement
|
||||
SwitchStatement *sw; // enclosing switch statement
|
||||
TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block
|
||||
Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Statement *sbreak; // enclosing statement that supports "break"
|
||||
Statement *scontinue; // enclosing statement that supports "continue"
|
||||
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
||||
unsigned offset; // next offset to use in aggregate
|
||||
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)
|
||||
int parameterSpecialization; // if in template parameter specialization
|
||||
int noaccesscheck; // don't do access checks
|
||||
|
||||
unsigned callSuper; // primitive flow analysis for constructors
|
||||
#define CSXthis_ctor 1 // called this()
|
||||
#define CSXsuper_ctor 2 // called super()
|
||||
#define CSXthis 4 // referenced this
|
||||
#define CSXsuper 8 // referenced super
|
||||
#define CSXlabel 0x10 // seen a label
|
||||
#define CSXreturn 0x20 // seen a return statement
|
||||
#define CSXany_ctor 0x40 // either this() or super() was called
|
||||
|
||||
unsigned structalign; // alignment for struct members
|
||||
enum LINK linkage; // linkage for external functions
|
||||
|
||||
enum PROT protection; // protection for class members
|
||||
int explicitProtection; // set if in an explicit protection attribute
|
||||
|
||||
unsigned stc; // storage class
|
||||
|
||||
unsigned flags;
|
||||
#define SCOPEctor 1 // constructor type
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
|
||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
||||
|
||||
DocComment *lastdc; // documentation comment for last symbol at this scope
|
||||
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
||||
OutBuffer *docbuf; // buffer for documentation output
|
||||
|
||||
static Scope *freelist;
|
||||
static void *operator new(size_t sz);
|
||||
static Scope *createGlobal(Module *module);
|
||||
|
||||
Scope();
|
||||
Scope(Module *module);
|
||||
Scope(Scope *enclosing);
|
||||
|
||||
Scope *push();
|
||||
Scope *push(ScopeDsymbol *ss);
|
||||
Scope *pop();
|
||||
|
||||
void mergeCallSuper(Loc loc, unsigned cs);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
ClassDeclaration *getClassScope();
|
||||
AggregateDeclaration *getStructClassScope();
|
||||
void setNoFree();
|
||||
};
|
||||
|
||||
#endif /* DMD_SCOPE_H */
|
||||
|
||||
// Copyright (c) 1999-2009 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_SCOPE_H
|
||||
#define DMD_SCOPE_H
|
||||
|
||||
#ifdef __DMC__
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
struct Dsymbol;
|
||||
struct ScopeDsymbol;
|
||||
struct Array;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
struct Statement;
|
||||
struct SwitchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct LabelStatement;
|
||||
struct ForeachStatement;
|
||||
struct ClassDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct AnonymousAggregateDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct DocComment;
|
||||
struct EnclosingHandler;
|
||||
struct AnonDeclaration;
|
||||
|
||||
#if __GNUC__
|
||||
#include "dsymbol.h" // PROT
|
||||
#include "mars.h" // LINK
|
||||
#else
|
||||
enum LINK;
|
||||
enum PROT;
|
||||
#endif
|
||||
|
||||
struct Scope
|
||||
{
|
||||
Scope *enclosing; // enclosing Scope
|
||||
|
||||
Module *module; // Root module
|
||||
ScopeDsymbol *scopesym; // current symbol
|
||||
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
|
||||
// sd gets the addMember()
|
||||
FuncDeclaration *func; // function we are in
|
||||
Dsymbol *parent; // parent to use
|
||||
LabelStatement *slabel; // enclosing labelled statement
|
||||
SwitchStatement *sw; // enclosing switch statement
|
||||
TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block
|
||||
Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
Statement *sbreak; // enclosing statement that supports "break"
|
||||
Statement *scontinue; // enclosing statement that supports "continue"
|
||||
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
||||
unsigned offset; // next offset to use in aggregate
|
||||
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)
|
||||
int parameterSpecialization; // if in template parameter specialization
|
||||
int noaccesscheck; // don't do access checks
|
||||
|
||||
unsigned callSuper; // primitive flow analysis for constructors
|
||||
#define CSXthis_ctor 1 // called this()
|
||||
#define CSXsuper_ctor 2 // called super()
|
||||
#define CSXthis 4 // referenced this
|
||||
#define CSXsuper 8 // referenced super
|
||||
#define CSXlabel 0x10 // seen a label
|
||||
#define CSXreturn 0x20 // seen a return statement
|
||||
#define CSXany_ctor 0x40 // either this() or super() was called
|
||||
|
||||
unsigned structalign; // alignment for struct members
|
||||
enum LINK linkage; // linkage for external functions
|
||||
|
||||
enum PROT protection; // protection for class members
|
||||
int explicitProtection; // set if in an explicit protection attribute
|
||||
|
||||
unsigned stc; // storage class
|
||||
|
||||
unsigned flags;
|
||||
#define SCOPEctor 1 // constructor type
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
|
||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
||||
|
||||
DocComment *lastdc; // documentation comment for last symbol at this scope
|
||||
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
||||
OutBuffer *docbuf; // buffer for documentation output
|
||||
|
||||
static Scope *freelist;
|
||||
static void *operator new(size_t sz);
|
||||
static Scope *createGlobal(Module *module);
|
||||
|
||||
Scope();
|
||||
Scope(Module *module);
|
||||
Scope(Scope *enclosing);
|
||||
|
||||
Scope *push();
|
||||
Scope *push(ScopeDsymbol *ss);
|
||||
Scope *pop();
|
||||
|
||||
void mergeCallSuper(Loc loc, unsigned cs);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
ClassDeclaration *getClassScope();
|
||||
AggregateDeclaration *getStructClassScope();
|
||||
void setNoFree();
|
||||
};
|
||||
|
||||
#endif /* DMD_SCOPE_H */
|
||||
|
||||
133
dmd/statement.c
133
dmd/statement.c
@@ -27,6 +27,7 @@
|
||||
#include "hdrgen.h"
|
||||
#include "parse.h"
|
||||
#include "template.h"
|
||||
#include "attrib.h"
|
||||
|
||||
/******************************** Statement ***************************/
|
||||
|
||||
@@ -207,6 +208,10 @@ Statement *ExpStatement::semantic(Scope *sc)
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp->checkSideEffect(0);
|
||||
exp = exp->optimize(0);
|
||||
if (exp->op == TOKdeclaration && !isDeclarationStatement())
|
||||
{ Statement *s = new DeclarationStatement(loc, exp);
|
||||
return s;
|
||||
}
|
||||
//exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
|
||||
}
|
||||
return this;
|
||||
@@ -576,6 +581,82 @@ int CompoundStatement::comeFrom()
|
||||
}
|
||||
|
||||
|
||||
/******************************** CompoundDeclarationStatement ***************************/
|
||||
|
||||
CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s)
|
||||
: CompoundStatement(loc, s)
|
||||
{
|
||||
statements = s;
|
||||
}
|
||||
|
||||
Statement *CompoundDeclarationStatement::syntaxCopy()
|
||||
{
|
||||
Statements *a = new Statements();
|
||||
a->setDim(statements->dim);
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *)statements->data[i];
|
||||
if (s)
|
||||
s = s->syntaxCopy();
|
||||
a->data[i] = s;
|
||||
}
|
||||
CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a);
|
||||
return cs;
|
||||
}
|
||||
|
||||
void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
int nwritten = 0;
|
||||
for (int i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
if (s)
|
||||
{ DeclarationStatement *ds = s->isDeclarationStatement();
|
||||
assert(ds);
|
||||
DeclarationExp *de = (DeclarationExp *)ds->exp;
|
||||
assert(de->op == TOKdeclaration);
|
||||
Declaration *d = de->declaration->isDeclaration();
|
||||
assert(d);
|
||||
VarDeclaration *v = d->isVarDeclaration();
|
||||
if (v)
|
||||
{
|
||||
/* This essentially copies the part of VarDeclaration::toCBuffer()
|
||||
* that does not print the type.
|
||||
* Should refactor this.
|
||||
*/
|
||||
if (nwritten)
|
||||
{
|
||||
buf->writeByte(',');
|
||||
buf->writestring(v->ident->toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
StorageClassDeclaration::stcToCBuffer(buf, v->storage_class);
|
||||
if (v->type)
|
||||
v->type->toCBuffer(buf, v->ident, hgs);
|
||||
else
|
||||
buf->writestring(v->ident->toChars());
|
||||
}
|
||||
|
||||
if (v->init)
|
||||
{ buf->writestring(" = ");
|
||||
#if DMDV2
|
||||
ExpInitializer *ie = v->init->isExpInitializer();
|
||||
if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
|
||||
((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
|
||||
else
|
||||
#endif
|
||||
v->init->toCBuffer(buf, hgs);
|
||||
}
|
||||
}
|
||||
else
|
||||
d->toCBuffer(buf, hgs);
|
||||
nwritten++;
|
||||
}
|
||||
}
|
||||
buf->writeByte(';');
|
||||
if (!hgs->FLinit.init)
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
/**************************** UnrolledLoopStatement ***************************/
|
||||
|
||||
UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
|
||||
@@ -889,6 +970,7 @@ int WhileStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int WhileStatement::comeFrom()
|
||||
{
|
||||
if (body)
|
||||
@@ -974,6 +1056,7 @@ int DoStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int DoStatement::comeFrom()
|
||||
{
|
||||
if (body)
|
||||
@@ -1103,6 +1186,7 @@ int ForStatement::blockExit()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int ForStatement::comeFrom()
|
||||
{
|
||||
//printf("ForStatement::comeFrom()\n");
|
||||
@@ -1120,11 +1204,7 @@ void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
if (init)
|
||||
{
|
||||
hgs->FLinit.init++;
|
||||
hgs->FLinit.decl = 0;
|
||||
init->toCBuffer(buf, hgs);
|
||||
if (hgs->FLinit.decl > 0)
|
||||
buf->writebyte(';');
|
||||
hgs->FLinit.decl = 0;
|
||||
hgs->FLinit.init--;
|
||||
}
|
||||
else
|
||||
@@ -1249,17 +1329,16 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
if (arg->storageClass & (STCout | STCref | STClazy))
|
||||
error("no storage class for key %s", arg->ident->toChars());
|
||||
TY keyty = arg->type->ty;
|
||||
if (global.params.is64bit)
|
||||
{
|
||||
if (keyty != Tint32 && keyty != Tuns32 && keyty != Tint64 && keyty != Tuns64)
|
||||
{
|
||||
error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars());
|
||||
}
|
||||
}
|
||||
else if (keyty != Tint32 && keyty != Tuns32)
|
||||
{
|
||||
error("foreach: key type must be int or uint, not %s", key->type->toChars());
|
||||
}
|
||||
if (keyty != Tint32 && keyty != Tuns32)
|
||||
{
|
||||
if (global.params.is64bit)
|
||||
{
|
||||
if (keyty != Tint64 && keyty != Tuns64)
|
||||
error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars());
|
||||
}
|
||||
else
|
||||
error("foreach: key type must be int or uint, not %s", arg->type->toChars());
|
||||
}
|
||||
Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
|
||||
VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
|
||||
var->storage_class |= STCconst;
|
||||
@@ -1391,20 +1470,16 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
tab->toChars(), value->type->toChars());
|
||||
}
|
||||
|
||||
if (key)
|
||||
{
|
||||
if (global.params.is64bit)
|
||||
{
|
||||
if (key->type->ty != Tint32 && key->type->ty != Tuns32 && key->type->ty != Tint64 && key->type->ty != Tuns64)
|
||||
{
|
||||
error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars());
|
||||
}
|
||||
}
|
||||
else if (key->type->ty != Tint32 && key->type->ty != Tuns32)
|
||||
{
|
||||
error("foreach: key type must be int or uint, not %s", key->type->toChars());
|
||||
}
|
||||
}
|
||||
if (key && key->type->ty != Tint32 && key->type->ty != Tuns32)
|
||||
{
|
||||
if (global.params.is64bit)
|
||||
{
|
||||
if (key->type->ty != Tint64 && key->type->ty != Tuns64)
|
||||
error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
|
||||
}
|
||||
else
|
||||
error("foreach: key type must be int or uint, not %s", key->type->toChars());
|
||||
}
|
||||
|
||||
if (key && key->storage_class & (STCout | STCref))
|
||||
error("foreach: key cannot be out or ref");
|
||||
|
||||
1771
dmd/statement.h
1771
dmd/statement.h
File diff suppressed because it is too large
Load Diff
1024
dmd/struct.c
1024
dmd/struct.c
File diff suppressed because it is too large
Load Diff
222
dmd/template.c
222
dmd/template.c
@@ -14,12 +14,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#if !IN_LLVM
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
#include "stringtable.h"
|
||||
@@ -36,6 +31,11 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
|
||||
#include "dsymbol.h"
|
||||
#include "hdrgen.h"
|
||||
|
||||
#if WINDOWS_SEH
|
||||
#include <windows.h>
|
||||
long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
|
||||
#endif
|
||||
|
||||
#define LOG 0
|
||||
|
||||
/********************************************
|
||||
@@ -159,6 +159,8 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
//printf("t1 = %s\n", t1->toChars());
|
||||
//printf("t2 = %s\n", t2->toChars());
|
||||
if (!t2 || !t1->equals(t2))
|
||||
goto Lnomatch;
|
||||
}
|
||||
@@ -186,7 +188,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
|
||||
{
|
||||
goto Lnomatch;
|
||||
}
|
||||
#if V2
|
||||
#if DMDV2
|
||||
VarDeclaration *v1 = s1->isVarDeclaration();
|
||||
VarDeclaration *v2 = s2->isVarDeclaration();
|
||||
if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest)
|
||||
@@ -263,7 +265,7 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
|
||||
}
|
||||
}
|
||||
|
||||
#if V2
|
||||
#if DMDV2
|
||||
Object *objectSyntaxCopy(Object *o)
|
||||
{
|
||||
if (!o)
|
||||
@@ -281,7 +283,8 @@ Object *objectSyntaxCopy(Object *o)
|
||||
|
||||
/* ======================== TemplateDeclaration ============================= */
|
||||
|
||||
TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Array *decldefs)
|
||||
TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
|
||||
TemplateParameters *parameters, Expression *constraint, Array *decldefs)
|
||||
: ScopeDsymbol(id)
|
||||
{
|
||||
#if LOG
|
||||
@@ -303,9 +306,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, TemplateParame
|
||||
this->loc = loc;
|
||||
this->parameters = parameters;
|
||||
this->origParameters = parameters;
|
||||
#if V2
|
||||
this->constraint = constraint;
|
||||
#endif
|
||||
this->members = decldefs;
|
||||
this->overnext = NULL;
|
||||
this->overroot = NULL;
|
||||
@@ -330,13 +331,11 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
|
||||
p->data[i] = (void *)tp->syntaxCopy();
|
||||
}
|
||||
}
|
||||
#if V2
|
||||
Expression *e = NULL;
|
||||
if (constraint)
|
||||
e = constraint->syntaxCopy();
|
||||
#endif
|
||||
d = Dsymbol::arraySyntaxCopy(members);
|
||||
td = new TemplateDeclaration(loc, ident, p, d);
|
||||
td = new TemplateDeclaration(loc, ident, p, e, d);
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC
|
||||
@@ -673,11 +672,11 @@ Lret:
|
||||
/********************************************
|
||||
* Determine partial specialization order of 'this' vs td2.
|
||||
* Returns:
|
||||
* 1 this is at least as specialized as td2
|
||||
* match this is at least as specialized as td2
|
||||
* 0 td2 is more specialized than this
|
||||
*/
|
||||
|
||||
int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
|
||||
MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
|
||||
{
|
||||
/* This works by taking the template parameters to this template
|
||||
* declaration and feeding them to td2 as if it were a template
|
||||
@@ -715,7 +714,8 @@ int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
|
||||
dedtypes.setDim(td2->parameters->dim);
|
||||
|
||||
// Attempt a type deduction
|
||||
if (td2->matchWithInstance(&ti, &dedtypes, 1))
|
||||
MATCH m = td2->matchWithInstance(&ti, &dedtypes, 1);
|
||||
if (m)
|
||||
{
|
||||
/* A non-variadic template is more specialized than a
|
||||
* variadic one.
|
||||
@@ -724,15 +724,15 @@ int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
|
||||
goto L1;
|
||||
|
||||
#if LOG_LEASTAS
|
||||
printf(" matches, so is least as specialized\n");
|
||||
printf(" matches %d, so is least as specialized\n", m);
|
||||
#endif
|
||||
return 1;
|
||||
return m;
|
||||
}
|
||||
L1:
|
||||
#if LOG_LEASTAS
|
||||
printf(" doesn't match, so is not as specialized\n");
|
||||
#endif
|
||||
return 0;
|
||||
return MATCHnomatch;
|
||||
}
|
||||
|
||||
|
||||
@@ -762,7 +762,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
||||
MATCH match = MATCHexact;
|
||||
FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
|
||||
TypeFunction *fdtype; // type of fd
|
||||
TemplateTupleParameter *tp;
|
||||
Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
|
||||
|
||||
#if 0
|
||||
@@ -786,7 +785,18 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
||||
paramsym->parent = scope->parent;
|
||||
Scope *paramscope = scope->push(paramsym);
|
||||
|
||||
tp = isVariadic();
|
||||
TemplateTupleParameter *tp = isVariadic();
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < dedargs->dim; i++)
|
||||
{
|
||||
printf("\tdedarg[%d] = ", i);
|
||||
Object *oarg = (Object *)dedargs->data[i];
|
||||
if (oarg) printf("%s", oarg->toChars());
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
nargsi = 0;
|
||||
if (targsi)
|
||||
@@ -802,11 +812,11 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
||||
|
||||
memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
|
||||
|
||||
for (i = 0; i < nargsi; i++)
|
||||
for (size_t i = 0; i < nargsi; i++)
|
||||
{ assert(i < parameters->dim);
|
||||
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
||||
MATCH m;
|
||||
Declaration *sparam;
|
||||
Declaration *sparam = NULL;
|
||||
|
||||
m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
|
||||
//printf("\tdeduceType m = %d\n", m);
|
||||
@@ -820,6 +830,15 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
||||
goto Lnomatch;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for (i = 0; i < dedargs->dim; i++)
|
||||
{
|
||||
printf("\tdedarg[%d] = ", i);
|
||||
Object *oarg = (Object *)dedargs->data[i];
|
||||
if (oarg) printf("%s", oarg->toChars());
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(fd->type->ty == Tfunction);
|
||||
fdtype = (TypeFunction *)fd->type;
|
||||
@@ -833,7 +852,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
||||
* template Foo(T, A...) { void Foo(T t, A a); }
|
||||
* void main() { Foo(1,2,3); }
|
||||
*/
|
||||
tp = isVariadic();
|
||||
if (tp) // if variadic
|
||||
{
|
||||
if (nfparams == 0) // if no function parameters
|
||||
@@ -906,7 +924,7 @@ L2:
|
||||
{ MATCH m;
|
||||
|
||||
Type *t = new TypeIdentifier(0, ttp->ident);
|
||||
m = ethis->type->deduceType(scope, t, parameters, &dedtypes);
|
||||
m = ethis->type->deduceType(paramscope, t, parameters, &dedtypes);
|
||||
if (!m)
|
||||
goto Lnomatch;
|
||||
if (m < match)
|
||||
@@ -946,9 +964,25 @@ L2:
|
||||
printf("\tfarg->type = %s\n", farg->type->toChars());
|
||||
printf("\tfparam->type = %s\n", fparam->type->toChars());
|
||||
#endif
|
||||
Type *argtype = farg->type;
|
||||
|
||||
#if DMDV2
|
||||
/* Allow string literals which are type [] to match with [dim]
|
||||
*/
|
||||
if (farg->op == TOKstring)
|
||||
{ StringExp *se = (StringExp *)farg;
|
||||
if (!se->committed && argtype->ty == Tarray &&
|
||||
fparam->type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(se->loc, se->len, Type::tindex));
|
||||
argtype = argtype->semantic(se->loc, NULL);
|
||||
argtype = argtype->invariantOf();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MATCH m;
|
||||
m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes);
|
||||
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
|
||||
//printf("\tdeduceType m = %d\n", m);
|
||||
|
||||
/* If no match, see if there's a conversion to a delegate
|
||||
@@ -960,7 +994,7 @@ L2:
|
||||
|
||||
if (!tf->varargs && Argument::dim(tf->parameters) == 0)
|
||||
{
|
||||
m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes);
|
||||
m = farg->type->deduceType(paramscope, tf->next, parameters, &dedtypes);
|
||||
if (!m && tf->next->toBasetype()->ty == Tvoid)
|
||||
m = MATCHconvert;
|
||||
}
|
||||
@@ -988,7 +1022,7 @@ L2:
|
||||
// Perhaps we can do better with this, see TypeFunction::callMatch()
|
||||
case Tsarray:
|
||||
{ TypeSArray *tsa = (TypeSArray *)tb;
|
||||
integer_t sz = tsa->dim->toInteger();
|
||||
dinteger_t sz = tsa->dim->toInteger();
|
||||
if (sz != nfargs - i)
|
||||
goto Lnomatch;
|
||||
}
|
||||
@@ -1020,7 +1054,7 @@ L2:
|
||||
}
|
||||
else
|
||||
{
|
||||
m = arg->type->deduceType(scope, ta->next, parameters, &dedtypes);
|
||||
m = arg->type->deduceType(paramscope, ta->next, parameters, &dedtypes);
|
||||
//m = arg->implicitConvTo(ta->next);
|
||||
}
|
||||
if (m == MATCHnomatch)
|
||||
@@ -1053,6 +1087,8 @@ Lmatch:
|
||||
Object *oarg = (Object *)dedargs->data[i];
|
||||
Object *oded = (Object *)dedtypes.data[i];
|
||||
//printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
|
||||
//if (oarg) printf("oarg: %s\n", oarg->toChars());
|
||||
//if (oded) printf("oded: %s\n", oded->toChars());
|
||||
if (!oarg)
|
||||
{
|
||||
if (oded)
|
||||
@@ -1134,6 +1170,22 @@ void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Obj
|
||||
|
||||
Dsymbol *s;
|
||||
|
||||
// See if tp->ident already exists with a matching definition
|
||||
Dsymbol *scopesym;
|
||||
s = sc->search(loc, tp->ident, &scopesym);
|
||||
if (s && scopesym == sc->scopesym)
|
||||
{
|
||||
TupleDeclaration *td = s->isTupleDeclaration();
|
||||
if (va && td)
|
||||
{ Tuple tup;
|
||||
tup.objects = *td->objects;
|
||||
if (match(va, &tup, this, sc))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targ)
|
||||
{
|
||||
//printf("type %s\n", targ->toChars());
|
||||
@@ -1267,8 +1319,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
|
||||
{
|
||||
// Disambiguate by picking the most specialized TemplateDeclaration
|
||||
int c1 = td->leastAsSpecialized(td_best);
|
||||
int c2 = td_best->leastAsSpecialized(td);
|
||||
MATCH c1 = td->leastAsSpecialized(td_best);
|
||||
MATCH c2 = td_best->leastAsSpecialized(td);
|
||||
//printf("c1 = %d, c2 = %d\n", c1, c2);
|
||||
|
||||
if (c1 > c2)
|
||||
@@ -1298,7 +1350,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
}
|
||||
if (!td_best)
|
||||
{
|
||||
error(loc, "does not match any template declaration");
|
||||
error(loc, "does not match any function template declaration");
|
||||
goto Lerror;
|
||||
}
|
||||
if (td_ambig)
|
||||
@@ -1319,6 +1371,9 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
||||
return fd;
|
||||
|
||||
Lerror:
|
||||
#if DMDV2
|
||||
if (!(flags & 1))
|
||||
#endif
|
||||
{
|
||||
HdrGenState hgs;
|
||||
|
||||
@@ -1537,8 +1592,29 @@ Lexact:
|
||||
|
||||
Lnomatch:
|
||||
return MATCHnomatch;
|
||||
|
||||
#if DMDV2
|
||||
Lconst:
|
||||
return MATCHconst;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||
Objects *dedtypes)
|
||||
{
|
||||
#if 0
|
||||
printf("TypeDArray::deduceType()\n");
|
||||
printf("\tthis = %d, ", ty); print();
|
||||
printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
||||
#endif
|
||||
return Type::deduceType(sc, tparam, parameters, dedtypes);
|
||||
|
||||
Lnomatch:
|
||||
return MATCHnomatch;
|
||||
}
|
||||
#endif
|
||||
|
||||
MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||
Objects *dedtypes)
|
||||
{
|
||||
@@ -1765,8 +1841,11 @@ MATCH TypeInstance::deduceType(Scope *sc,
|
||||
Type *tparam, TemplateParameters *parameters,
|
||||
Objects *dedtypes)
|
||||
{
|
||||
//printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
|
||||
//printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
||||
#if 0
|
||||
printf("TypeInstance::deduceType()\n");
|
||||
printf("\tthis = %d, ", ty); print();
|
||||
printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
||||
#endif
|
||||
|
||||
// Extra check
|
||||
if (tparam && tparam->ty == Tinstance)
|
||||
@@ -1802,14 +1881,14 @@ MATCH TypeInstance::deduceType(Scope *sc,
|
||||
TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
|
||||
if (!ta)
|
||||
goto Lnomatch;
|
||||
Dsymbol *sa = tempinst->tempdecl;
|
||||
Object *sa = tempinst->tempdecl;
|
||||
if (!sa)
|
||||
goto Lnomatch;
|
||||
if (ta->specAlias && sa != ta->specAlias)
|
||||
goto Lnomatch;
|
||||
if (dedtypes->data[i])
|
||||
{ // Must match already deduced symbol
|
||||
Dsymbol *s = (Dsymbol *)dedtypes->data[i];
|
||||
Object *s = (Object *)dedtypes->data[i];
|
||||
|
||||
if (s != sa)
|
||||
goto Lnomatch;
|
||||
@@ -1821,12 +1900,13 @@ MATCH TypeInstance::deduceType(Scope *sc,
|
||||
goto Lnomatch;
|
||||
|
||||
L2:
|
||||
if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim)
|
||||
goto Lnomatch;
|
||||
|
||||
for (int i = 0; i < tempinst->tiargs->dim; i++)
|
||||
{
|
||||
//printf("\ttest: tempinst->tiargs[%d]\n", i);
|
||||
if (i >= tp->tempinst->tiargs->dim)
|
||||
goto Lnomatch;
|
||||
|
||||
int j;
|
||||
Object *o1 = (Object *)tempinst->tiargs->data[i];
|
||||
Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
|
||||
@@ -1853,6 +1933,43 @@ MATCH TypeInstance::deduceType(Scope *sc,
|
||||
if (v2) printf("v2 = %s\n", v2->toChars());
|
||||
#endif
|
||||
|
||||
TemplateTupleParameter *ttp;
|
||||
if (t2 &&
|
||||
t2->ty == Tident &&
|
||||
i == tp->tempinst->tiargs->dim - 1 &&
|
||||
i == tempinst->tempdecl->parameters->dim - 1 &&
|
||||
(ttp = tempinst->tempdecl->isVariadic()) != NULL)
|
||||
{
|
||||
/* Given:
|
||||
* struct A(B...) {}
|
||||
* alias A!(int, float) X;
|
||||
* static if (!is(X Y == A!(Z), Z))
|
||||
* deduce that Z is a tuple(int, float)
|
||||
*/
|
||||
|
||||
j = templateParameterLookup(t2, parameters);
|
||||
if (j == -1)
|
||||
goto Lnomatch;
|
||||
|
||||
/* Create tuple from remaining args
|
||||
*/
|
||||
Tuple *vt = new Tuple();
|
||||
int vtdim = tempinst->tiargs->dim - i;
|
||||
vt->objects.setDim(vtdim);
|
||||
for (size_t k = 0; k < vtdim; k++)
|
||||
vt->objects.data[k] = (void *)tempinst->tiargs->data[i + k];
|
||||
|
||||
Tuple *v = (Tuple *)dedtypes->data[j];
|
||||
if (v)
|
||||
{
|
||||
if (!match(v, vt, tempinst->tempdecl, sc))
|
||||
goto Lnomatch;
|
||||
}
|
||||
else
|
||||
dedtypes->data[j] = vt;
|
||||
break; //return MATCHexact;
|
||||
}
|
||||
|
||||
if (t1 && t2)
|
||||
{
|
||||
if (!t1->deduceType(sc, t2, parameters, dedtypes))
|
||||
@@ -3299,11 +3416,9 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
sc2->parent = /*isnested ? sc->parent :*/ this;
|
||||
sc2->tinst = this;
|
||||
|
||||
#if !IN_LLVM
|
||||
#if _WIN32
|
||||
#if WINDOWS_SEH
|
||||
__try
|
||||
{
|
||||
#endif
|
||||
#endif
|
||||
for (int i = 0; i < members->dim; i++)
|
||||
{
|
||||
@@ -3317,8 +3432,7 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
//printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
|
||||
sc2->module->runDeferredSemantic();
|
||||
}
|
||||
#if !IN_LLVM
|
||||
#if _WIN32
|
||||
#if WINDOWS_SEH
|
||||
}
|
||||
__except (__ehfilter(GetExceptionInformation()))
|
||||
{
|
||||
@@ -3326,7 +3440,6 @@ void TemplateInstance::semantic(Scope *sc)
|
||||
error("recursive expansion");
|
||||
fatal();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* If any of the instantiation members didn't get semantic() run
|
||||
@@ -3385,10 +3498,15 @@ void TemplateInstance::semanticTiargs(Scope *sc)
|
||||
if (semantictiargsdone)
|
||||
return;
|
||||
semantictiargsdone = 1;
|
||||
semanticTiargs(loc, sc, tiargs);
|
||||
semanticTiargs(loc, sc, tiargs, 0);
|
||||
}
|
||||
|
||||
void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs)
|
||||
/**********************************
|
||||
* Input:
|
||||
* flags 1: replace const variables with their initializers
|
||||
*/
|
||||
|
||||
void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
|
||||
{
|
||||
// Run semantic on each argument, place results in tiargs[]
|
||||
//printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
|
||||
@@ -3636,8 +3754,8 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
|
||||
|
||||
{
|
||||
// Disambiguate by picking the most specialized TemplateDeclaration
|
||||
int c1 = td->leastAsSpecialized(td_best);
|
||||
int c2 = td_best->leastAsSpecialized(td);
|
||||
MATCH c1 = td->leastAsSpecialized(td_best);
|
||||
MATCH c2 = td_best->leastAsSpecialized(td);
|
||||
//printf("c1 = %d, c2 = %d\n", c1, c2);
|
||||
|
||||
if (c1 > c2)
|
||||
@@ -3667,7 +3785,11 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
|
||||
|
||||
if (!td_best)
|
||||
{
|
||||
error("%s does not match any template declaration", toChars());
|
||||
if (tempdecl && !tempdecl->overnext)
|
||||
// Only one template, so we can give better error message
|
||||
error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
|
||||
else
|
||||
error("%s does not match any template declaration", toChars());
|
||||
return NULL;
|
||||
}
|
||||
if (td_ambig)
|
||||
@@ -3777,7 +3899,7 @@ int TemplateInstance::hasNestedArgs(Objects *args)
|
||||
nested |= 1;
|
||||
}
|
||||
else
|
||||
error("cannot use local '%s' as template parameter", d->toChars());
|
||||
error("cannot use local '%s' as parameter to non-global template %s", d->toChars(), tempdecl->toChars());
|
||||
}
|
||||
}
|
||||
else if (va)
|
||||
|
||||
@@ -54,9 +54,7 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
TemplateParameters *parameters; // array of TemplateParameter's
|
||||
|
||||
TemplateParameters *origParameters; // originals for Ddoc
|
||||
#if DMDV2
|
||||
Expression *constraint;
|
||||
#endif
|
||||
Array instances; // array of TemplateInstance's
|
||||
|
||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||
@@ -66,10 +64,7 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||
|
||||
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
|
||||
#if DMDV2
|
||||
Expression *constraint,
|
||||
#endif
|
||||
Array *decldefs);
|
||||
Expression *constraint, Array *decldefs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
@@ -81,7 +76,7 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
// void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
|
||||
int leastAsSpecialized(TemplateDeclaration *td2);
|
||||
MATCH leastAsSpecialized(TemplateDeclaration *td2);
|
||||
|
||||
MATCH deduceFunctionTemplateMatch(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);
|
||||
@@ -108,6 +103,8 @@ struct TemplateParameter
|
||||
* template Foo(valType ident : specValue)
|
||||
* For alias-parameter:
|
||||
* template Foo(alias ident)
|
||||
* For this-parameter:
|
||||
* template Foo(this ident)
|
||||
*/
|
||||
|
||||
Loc loc;
|
||||
@@ -216,7 +213,7 @@ struct TemplateValueParameter : TemplateParameter
|
||||
struct TemplateAliasParameter : TemplateParameter
|
||||
{
|
||||
/* Syntax:
|
||||
* ident : specAlias = defaultAlias
|
||||
* specType ident : specAlias = defaultAlias
|
||||
*/
|
||||
|
||||
Type *specAliasT;
|
||||
@@ -317,7 +314,7 @@ struct TemplateInstance : ScopeDsymbol
|
||||
#endif
|
||||
|
||||
// Internal
|
||||
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs);
|
||||
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
|
||||
void semanticTiargs(Scope *sc);
|
||||
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
|
||||
TemplateDeclaration *findBestMatch(Scope *sc);
|
||||
|
||||
Reference in New Issue
Block a user