Merged 1.075 frontend.

This commit is contained in:
David Nadlinger
2012-11-24 20:58:26 +01:00
parent 2d02270434
commit 288fd47707
49 changed files with 2306 additions and 2082 deletions

View File

@@ -66,7 +66,7 @@ struct AggregateDeclaration : ScopeDsymbol
Type *handle; // 'this' type
unsigned structsize; // size of struct
unsigned alignsize; // size of struct for alignment purposes
unsigned structalign; // struct member alignment in effect
structalign_t structalign; // struct member alignment in effect
int hasUnions; // set if aggregate has overlapping fields
VarDeclarations fields; // VarDeclaration fields
enum Sizeok sizeok; // set when structsize contains valid data
@@ -102,9 +102,9 @@ struct AggregateDeclaration : ScopeDsymbol
void semantic3(Scope *sc);
void inlineScan();
unsigned size(Loc loc);
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
static void alignmember(structalign_t salign, unsigned size, unsigned *poffset);
static unsigned placeField(unsigned *nextoffset,
unsigned memsize, unsigned memalignsize, unsigned memalign,
unsigned memsize, unsigned memalignsize, structalign_t memalign,
unsigned *paggsize, unsigned *paggalignsize, bool isunion);
Type *getType();
int firstFieldInUnion(int indx); // first field in union that includes indx
@@ -156,13 +156,19 @@ struct StructDeclaration : AggregateDeclaration
int zeroInit; // !=0 if initialize with 0 fill
#if DMDV2
int hasIdentityAssign; // !=0 if has identity opAssign
int hasIdentityEquals; // !=0 if has identity opEquals
FuncDeclaration *cpctor; // generated copy-constructor, if any
FuncDeclaration *eq; // bool opEquals(ref const T), if any
FuncDeclarations postblits; // Array of postblit functions
FuncDeclaration *postblit; // aggregate postblit
FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals
static FuncDeclaration *xerreq; // object.xopEquals
#endif
// For 64 bit Efl function call/return ABI
Type *arg1type;
Type *arg2type;
StructDeclaration(Loc loc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
@@ -171,6 +177,7 @@ struct StructDeclaration : AggregateDeclaration
char *mangle();
const char *kind();
void finalizeSize(Scope *sc);
bool isPOD();
#if DMDV1
Expression *cloneMembers();
#endif

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 2010-2011 by Digital Mars
// Copyright (c) 2010-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -27,6 +27,9 @@
#include "aggregate.h"
#include "hdrgen.h"
#define tfloat2 tfloat64
//#define tfloat2 tcomplex32
/****************************************************
* This breaks a type down into 'simpler' types that can be passed to a function
* in registers, and returned in registers.
@@ -40,6 +43,10 @@ TypeTuple *Type::toArgTypes()
return NULL; // not valid for a parameter
}
TypeTuple *TypeError::toArgTypes()
{
return new TypeTuple(Type::terror);
}
TypeTuple *TypeBasic::toArgTypes()
{ Type *t1 = NULL;
@@ -78,7 +85,7 @@ TypeTuple *TypeBasic::toArgTypes()
case Tcomplex32:
if (global.params.is64bit)
t1 = Type::tfloat64; // weird, eh?
t1 = Type::tfloat2;
else
{
t1 = Type::tfloat64;
@@ -87,8 +94,8 @@ TypeTuple *TypeBasic::toArgTypes()
break;
case Tcomplex64:
//t1 = Type::tfloat64;
//t2 = Type::tfloat64;
t1 = Type::tfloat64;
t2 = Type::tfloat64;
break;
case Tcomplex80:
@@ -124,18 +131,39 @@ TypeTuple *TypeBasic::toArgTypes()
return t;
}
#if DMDV2
TypeTuple *TypeVector::toArgTypes()
{
return new TypeTuple(this);
}
#endif
TypeTuple *TypeSArray::toArgTypes()
{
#if DMDV2
if (dim)
{
/* Should really be done as if it were a struct with dim members
* of the array's elements.
* I.e. int[2] should be done like struct S { int a; int b; }
*/
dinteger_t sz = dim->toInteger();
if (sz == 1)
// T[1] should be passed like T
return next->toArgTypes();
}
return new TypeTuple(); // pass on the stack for efficiency
#else
return new TypeTuple(Type::tvoidptr);
return new TypeTuple(); // pass on the stack for efficiency
#endif
}
TypeTuple *TypeDArray::toArgTypes()
{
return new TypeTuple(); // pass on the stack for efficiency
/* Should be done as if it were:
* struct S { size_t length; void* ptr; }
*/
return new TypeTuple(Type::tsize_t, Type::tvoidptr);
}
TypeTuple *TypeAArray::toArgTypes()
@@ -145,30 +173,255 @@ TypeTuple *TypeAArray::toArgTypes()
TypeTuple *TypePointer::toArgTypes()
{
return new TypeTuple(this);
return new TypeTuple(Type::tvoidptr);
}
TypeTuple *TypeDelegate::toArgTypes()
{
return new TypeTuple(); // pass on the stack for efficiency
/* Should be done as if it were:
* struct S { void* ptr; void* funcptr; }
*/
return new TypeTuple(Type::tvoidptr, Type::tvoidptr);
}
/*************************************
* Convert a floating point type into the equivalent integral type.
*/
Type *mergeFloatToInt(Type *t)
{
switch (t->ty)
{
case Tfloat32:
case Timaginary32:
t = Type::tint32;
break;
case Tfloat64:
case Timaginary64:
case Tcomplex32:
t = Type::tint64;
break;
default:
#ifdef DEBUG
printf("mergeFloatToInt() %s\n", t->toChars());
#endif
assert(0);
}
return t;
}
/*************************************
* This merges two types into an 8byte type.
*/
Type *argtypemerge(Type *t1, Type *t2, unsigned offset2)
{
//printf("argtypemerge(%s, %s, %d)\n", t1 ? t1->toChars() : "", t2 ? t2->toChars() : "", offset2);
if (!t1)
{ assert(!t2 || offset2 == 0);
return t2;
}
if (!t2)
return t1;
unsigned sz1 = t1->size(0);
unsigned sz2 = t2->size(0);
if (t1->ty != t2->ty &&
(t1->ty == Tfloat80 || t2->ty == Tfloat80))
return NULL;
// [float,float] => [cfloat]
if (t1->ty == Tfloat32 && t2->ty == Tfloat32 && offset2 == 4)
return Type::tfloat2;
// Merging floating and non-floating types produces the non-floating type
if (t1->isfloating())
{
if (!t2->isfloating())
t1 = mergeFloatToInt(t1);
}
else if (t2->isfloating())
t2 = mergeFloatToInt(t2);
Type *t;
// Pick type with larger size
if (sz1 < sz2)
t = t2;
else
t = t1;
// If t2 does not lie within t1, need to increase the size of t to enclose both
if (offset2 && sz1 < offset2 + sz2)
{
switch (offset2 + sz2)
{
case 2:
t = Type::tint16;
break;
case 3:
case 4:
t = Type::tint32;
break;
case 5:
case 6:
case 7:
case 8:
t = Type::tint64;
break;
default:
assert(0);
}
}
return t;
}
TypeTuple *TypeStruct::toArgTypes()
{
//printf("TypeStruct::toArgTypes() %s\n", toChars());
if (!sym->isPOD())
{
Lmemory:
//printf("\ttoArgTypes() %s => [ ]\n", toChars());
return new TypeTuple(); // pass on the stack
}
Type *t1 = NULL;
Type *t2 = NULL;
d_uns64 sz = size(0);
assert(sz < 0xFFFFFFFF);
switch ((unsigned)sz)
{
case 1:
return new TypeTuple(Type::tint8);
t1 = Type::tint8;
break;
case 2:
return new TypeTuple(Type::tint16);
t1 = Type::tint16;
break;
case 4:
return new TypeTuple(Type::tint32);
t1 = Type::tint32;
break;
case 8:
return new TypeTuple(Type::tint64);
t1 = Type::tint64;
break;
case 16:
t1 = NULL; // could be a TypeVector
break;
default:
goto Lmemory;
}
return new TypeTuple(); // pass on the stack
if (global.params.is64bit && sym->fields.dim)
{
#if 1
unsigned sz1 = 0;
unsigned sz2 = 0;
t1 = NULL;
for (size_t i = 0; i < sym->fields.dim; i++)
{ VarDeclaration *f = sym->fields[i];
//printf("f->type = %s\n", f->type->toChars());
TypeTuple *tup = f->type->toArgTypes();
if (!tup)
goto Lmemory;
size_t dim = tup->arguments->dim;
Type *ft1 = NULL;
Type *ft2 = NULL;
switch (dim)
{
case 2:
ft1 = (*tup->arguments)[0]->type;
ft2 = (*tup->arguments)[1]->type;
break;
case 1:
if (f->offset < 8)
ft1 = (*tup->arguments)[0]->type;
else
ft2 = (*tup->arguments)[0]->type;
break;
default:
goto Lmemory;
}
if (f->offset & 7)
{
// Misaligned fields goto Lmemory
unsigned alignsz = f->type->alignsize();
if (f->offset & (alignsz - 1))
goto Lmemory;
// Fields that overlap the 8byte boundary goto Lmemory
unsigned fieldsz = f->type->size(0);
if (f->offset < 8 && (f->offset + fieldsz) > 8)
goto Lmemory;
}
// First field in 8byte must be at start of 8byte
assert(t1 || f->offset == 0);
if (ft1)
{
t1 = argtypemerge(t1, ft1, f->offset);
if (!t1)
goto Lmemory;
}
if (ft2)
{
unsigned off2 = f->offset;
if (ft1)
off2 = 8;
assert(t2 || off2 == 8);
t2 = argtypemerge(t2, ft2, off2 - 8);
if (!t2)
goto Lmemory;
}
}
if (t2)
{
if (t1->isfloating() && t2->isfloating())
{
if (t1->ty == Tfloat64 && t2->ty == Tfloat64)
;
else
goto Lmemory;
}
else if (t1->isfloating())
goto Lmemory;
else if (t2->isfloating())
goto Lmemory;
else
;
}
#else
if (sym->fields.dim == 1)
{ VarDeclaration *f = sym->fields[0];
//printf("f->type = %s\n", f->type->toChars());
TypeTuple *tup = f->type->toArgTypes();
if (tup)
{
size_t dim = tup->arguments->dim;
if (dim == 1)
t1 = (*tup->arguments)[0]->type;
}
}
#endif
}
//printf("\ttoArgTypes() %s => [%s,%s]\n", toChars(), t1 ? t1->toChars() : "", t2 ? t2->toChars() : "");
TypeTuple *t;
if (t1)
{
//if (t1) printf("test1: %s => %s\n", toChars(), t1->toChars());
if (t2)
t = new TypeTuple(t1, t2);
else
t = new TypeTuple(t1);
}
else
goto Lmemory;
return t;
}
TypeTuple *TypeEnum::toArgTypes()

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -92,7 +92,9 @@ Expression *BinExp::arrayOp(Scope *sc)
{
//printf("BinExp::arrayOp() %s\n", toChars());
if (type->toBasetype()->nextOf()->toBasetype()->ty == Tvoid)
Type *tb = type->toBasetype();
assert(tb->ty == Tarray || tb->ty == Tsarray);
if (tb->nextOf()->toBasetype()->ty == Tvoid)
{
error("Cannot perform array operations on void[] arrays");
return new ErrorExp();
@@ -123,7 +125,10 @@ Expression *BinExp::arrayOp(Scope *sc)
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
#endif
size_t namelen = buf.offset;
#if IN_LLVM
const size_t namelen = buf.offset;
#endif
buf.writeByte(0);
char *name = buf.toChars();
Identifier *ident = Lexer::idPool(name);
@@ -337,7 +342,7 @@ Expression *BinExp::arrayOp(Scope *sc)
// foreach (i; 0 .. p.length)
Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
new Parameter(0, NULL, Id::p, NULL),
new IntegerExp(0, 0, Type::tint32),
new IntegerExp(0, 0, Type::tsize_t),
new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
new ExpStatement(0, loopbody));
#endif

View File

@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // memcpy()
#include "rmem.h"
@@ -34,7 +35,7 @@
#endif
extern void obj_includelib(const char *name);
extern bool obj_includelib(const char *name);
#if IN_DMD
void obj_startaddress(Symbol *s);
@@ -90,7 +91,7 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
void AttribDeclaration::setScopeNewSc(Scope *sc,
StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection,
unsigned structalign)
structalign_t structalign)
{
if (decl)
{
@@ -125,7 +126,7 @@ void AttribDeclaration::setScopeNewSc(Scope *sc,
void AttribDeclaration::semanticNewSc(Scope *sc,
StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection,
unsigned structalign)
structalign_t structalign)
{
if (decl)
{
@@ -425,6 +426,7 @@ void StorageClassDeclaration::setScope(Scope *sc)
if (stc & (STCsafe | STCtrusted | STCsystem))
scstc &= ~(STCsafe | STCtrusted | STCsystem);
scstc |= stc;
//printf("scstc = x%llx\n", scstc);
setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
}
@@ -732,6 +734,9 @@ void AlignDeclaration::semantic(Scope *sc)
void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (salign == STRUCTALIGN_DEFAULT)
buf->printf("align");
else
buf->printf("align (%d)", salign);
AttribDeclaration::toCBuffer(buf, hgs);
}
@@ -924,7 +929,7 @@ void PragmaDeclaration::setScope(Scope *sc)
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
(*args)[0] = e;
StringExp* se = e->toString();
if (!se)
@@ -963,7 +968,8 @@ void PragmaDeclaration::semantic(Scope *sc)
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->op != TOKerror && e->op != TOKtype)
e = e->ctfeInterpret();
StringExp *se = e->toString();
if (se)
{
@@ -985,7 +991,7 @@ void PragmaDeclaration::semantic(Scope *sc)
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
(*args)[0] = e;
if (e->op == TOKerror)
goto Lnodecl;
@@ -1049,7 +1055,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
(*args)[0] = e;
Dsymbol *sa = getDsymbol(e);
if (!sa || !sa->isFuncDeclaration())
@@ -1088,7 +1094,7 @@ void PragmaDeclaration::semantic(Scope *sc)
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
if (i == 0)
printf(" (");
else
@@ -1161,21 +1167,19 @@ void PragmaDeclaration::toObjFile(int multiobj)
char *name = (char *)mem.malloc(se->len + 1);
memcpy(name, se->string, se->len);
name[se->len] = 0;
#if OMFOBJ
/* The OMF format allows library names to be inserted
* into the object file. The linker will then automatically
/* Embed the library names into the object file.
* The linker will then automatically
* search that library, too.
*/
obj_includelib(name);
#elif ELFOBJ || MACHOBJ
if (!obj_includelib(name))
{
/* The format does not allow embedded library names,
* so instead append the library name to the list to be passed
* to the linker.
*/
global.params.libfiles->push(name);
#else
error("pragma lib not supported");
#endif
}
}
#if DMDV2
else if (ident == Id::startaddress)
@@ -1431,6 +1435,26 @@ void StaticIfDeclaration::importAll(Scope *sc)
void StaticIfDeclaration::setScope(Scope *sc)
{
// do not evaluate condition before semantic pass
// But do set the scope, in case we need it for forward referencing
Dsymbol::setScope(sc);
// Set the scopes for both the decl and elsedecl, as we don't know yet
// which will be selected, and the scope will be the same regardless
Dsymbols *d = decl;
for (int j = 0; j < 2; j++)
{
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = (*d)[i];
s->setScope(sc);
}
}
d = elsedecl;
}
}
void StaticIfDeclaration::semantic(Scope *sc)
@@ -1462,6 +1486,8 @@ const char *StaticIfDeclaration::kind()
/***************************** CompileDeclaration *****************************/
// These are mixin declarations, like mixin("int x");
CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
: AttribDeclaration(NULL)
{
@@ -1481,7 +1507,7 @@ Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
//printf("CompileDeclaration::addMember(sc = %p, memnum = %d)\n", sc, memnum);
//printf("CompileDeclaration::addMember(sc = %p, sd = %p, memnum = %d)\n", sc, sd, memnum);
this->sd = sd;
if (memnum == 0)
{ /* No members yet, so parse the mixin now
@@ -1495,10 +1521,10 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
void CompileDeclaration::compileIt(Scope *sc)
{
//printf("CompileDeclaration::compileIt(loc = %d)\n", loc.linnum);
//printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
exp = exp->optimize(WANTvalue | WANTinterpret);
exp = exp->ctfeInterpret();
StringExp *se = exp->toString();
if (!se)
{ exp->error("argument to mixin must be a string, not (%s)", exp->toChars());

View File

@@ -37,10 +37,10 @@ struct AttribDeclaration : Dsymbol
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void setScopeNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
structalign_t structalign);
void semanticNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
structalign_t structalign);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
@@ -121,7 +121,7 @@ struct AlignDeclaration : AttribDeclaration
struct AnonDeclaration : AttribDeclaration
{
bool isunion;
unsigned alignment;
structalign_t alignment;
int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h> // mem{set|cpy}()
#include "rmem.h"
@@ -172,6 +173,7 @@ MATCH IntegerExp::implicitConvTo(Type *t)
enum TY ty = type->toBasetype()->ty;
enum TY toty = t->toBasetype()->ty;
enum TY oldty = ty;
if (type->implicitConvTo(t) == MATCHnomatch && t->ty == Tenum)
{
@@ -237,6 +239,8 @@ MATCH IntegerExp::implicitConvTo(Type *t)
goto Lyes;
case Tchar:
if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
goto Lno;
case Tuns8:
//printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
if ((unsigned char)value != value)
@@ -248,6 +252,9 @@ MATCH IntegerExp::implicitConvTo(Type *t)
goto Lno;
goto Lyes;
case Twchar:
if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
goto Lno;
case Tuns16:
if ((unsigned short)value != value)
goto Lno;
@@ -274,11 +281,6 @@ MATCH IntegerExp::implicitConvTo(Type *t)
goto Lno;
goto Lyes;
case Twchar:
if ((unsigned short)value != value)
goto Lno;
goto Lyes;
case Tfloat32:
{
volatile float f;
@@ -467,13 +469,17 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t)
result = MATCHnomatch;
}
if (!elements->dim && typeb->nextOf()->toBasetype()->ty != Tvoid)
result = MATCHnomatch;
Type *telement = tb->nextOf();
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (*elements)[i];
MATCH m = (MATCH)e->implicitConvTo(tb->nextOf());
if (m < result)
result = m; // remember worst match
if (result == MATCHnomatch)
break; // no need to check for worse
MATCH m = (MATCH)e->implicitConvTo(telement);
if (m < result)
result = m; // remember worst match
}
if (!result)
@@ -481,6 +487,29 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t)
return result;
}
#if DMDV2
else if (tb->ty == Tvector &&
(typeb->ty == Tarray || typeb->ty == Tsarray))
{
// Convert array literal to vector type
TypeVector *tv = (TypeVector *)tb;
TypeSArray *tbase = (TypeSArray *)tv->basetype;
assert(tbase->ty == Tsarray);
if (elements->dim != tbase->dim->toInteger())
return MATCHnomatch;
Type *telement = tv->elementType();
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (*elements)[i];
MATCH m = (MATCH)e->implicitConvTo(telement);
if (m < result)
result = m; // remember worst match
if (result == MATCHnomatch)
break; // no need to check for worse
}
return result;
}
#endif
else
return Expression::implicitConvTo(t);
}
@@ -1063,6 +1092,30 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
e = (ArrayLiteralExp *)copy();
e->type = typeb->nextOf()->pointerTo();
}
#if DMDV2
else if (tb->ty == Tvector &&
(typeb->ty == Tarray || typeb->ty == Tsarray))
{
// Convert array literal to vector type
TypeVector *tv = (TypeVector *)tb;
TypeSArray *tbase = (TypeSArray *)tv->basetype;
assert(tbase->ty == Tsarray);
if (elements->dim != tbase->dim->toInteger())
goto L1;
e = (ArrayLiteralExp *)copy();
e->elements = (Expressions *)elements->copy();
Type *telement = tv->elementType();
for (size_t i = 0; i < elements->dim; i++)
{ Expression *ex = (*elements)[i];
ex = ex->castTo(sc, telement);
(*e->elements)[i] = ex;
}
Expression *ev = new VectorExp(loc, e, tb);
ev = ev->semantic(sc);
return ev;
}
#endif
L1:
return e->Expression::castTo(sc, t);
}

View File

@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // mem{cpy|set}()
#include "root.h"
#include "rmem.h"
@@ -228,9 +229,9 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
cd->baseclasses->setDim(this->baseclasses->dim);
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{
BaseClass *b = this->baseclasses->tdata()[i];
BaseClass *b = (*this->baseclasses)[i];
BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
cd->baseclasses->tdata()[i] = b2;
(*cd->baseclasses)[i] = b2;
}
ScopeDsymbol::syntaxCopy(cd);
@@ -290,7 +291,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; )
{ BaseClass *b = baseclasses->tdata()[i];
{ BaseClass *b = (*baseclasses)[i];
b->type = b->type->semantic(loc, sc);
Type *tb = b->type->toBasetype();
@@ -315,7 +316,7 @@ void ClassDeclaration::semantic(Scope *sc)
BaseClass *b;
Type *tb;
b = baseclasses->tdata()[0];
b = (*baseclasses)[0];
//b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype();
if (tb->ty != Tclass)
@@ -385,7 +386,7 @@ void ClassDeclaration::semantic(Scope *sc)
BaseClass *b;
Type *tb;
b = baseclasses->tdata()[i];
b = (*baseclasses)[i];
b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype();
if (tb->ty == Tclass)
@@ -414,7 +415,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Check for duplicate interfaces
for (size_t j = (baseClass ? 1 : 0); j < i; j++)
{
BaseClass *b2 = baseclasses->tdata()[j];
BaseClass *b2 = (*baseclasses)[j];
if (b2->base == tc->sym)
error("inherits from duplicate interface %s", b2->base->toChars());
}
@@ -446,22 +447,20 @@ void ClassDeclaration::semantic(Scope *sc)
// If no base class, and this is not an Object, use Object as base class
if (!baseClass && ident != Id::Object)
{
// BUG: what if Object is redefined in an inner scope?
Type *tbase = new TypeIdentifier(0, Id::Object);
BaseClass *b;
TypeClass *tc;
Type *bt;
if (!object)
{
error("missing or corrupt object.d");
fatal();
}
bt = tbase->semantic(loc, sc)->toBasetype();
b = new BaseClass(bt, PROTpublic);
Type *t = object->type;
t = t->semantic(loc, sc)->toBasetype();
assert(t->ty == Tclass);
TypeClass *tc = (TypeClass *)t;
BaseClass *b = new BaseClass(tc, PROTpublic);
baseclasses->shift(b);
assert(b->type->ty == Tclass);
tc = (TypeClass *)(b->type);
baseClass = tc->sym;
assert(!baseClass->isInterfaceDeclaration());
b->base = baseClass;
@@ -516,7 +515,9 @@ void ClassDeclaration::semantic(Scope *sc)
isnested = 1;
if (storage_class & STCstatic)
error("static class cannot inherit from nested class %s", baseClass->toChars());
if (toParent2() != baseClass->toParent2())
if (toParent2() != baseClass->toParent2() &&
(!toParent2() ||
!baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
{
if (toParent2())
{
@@ -592,7 +593,7 @@ void ClassDeclaration::semantic(Scope *sc)
}
sc->protection = PROTpublic;
sc->explicitProtection = 0;
sc->structalign = 8;
sc->structalign = STRUCTALIGN_DEFAULT;
structalign = sc->structalign;
if (baseClass)
{ sc->offset = baseClass->structsize;
@@ -620,9 +621,10 @@ void ClassDeclaration::semantic(Scope *sc)
if (s->isEnumDeclaration() ||
(s->isAggregateDeclaration() && s->ident) ||
s->isTemplateMixin() ||
s->isAttribDeclaration() ||
s->isAliasDeclaration())
{
//printf("setScope %s %s\n", s->kind(), s->toChars());
//printf("[%d] setScope %s %s, sc = %p\n", i, s->kind(), s->toChars(), sc);
s->setScope(sc);
}
}
@@ -756,7 +758,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Fill in base class vtbl[]s
for (i = 0; i < vtblInterfaces->dim; i++)
{
BaseClass *b = vtblInterfaces->tdata()[i];
BaseClass *b = (*vtblInterfaces)[i];
//b->fillVtbl(this, &b->vtbl, 1);
}
@@ -775,7 +777,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
for (size_t i = 0; i < baseclasses->dim; i++)
{
BaseClass *b = baseclasses->tdata()[i];
BaseClass *b = (*baseclasses)[i];
if (i)
buf->writeByte(',');
@@ -789,7 +791,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
@@ -824,7 +826,7 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
return 0;
//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{ BaseClass *b = cd->baseclasses->tdata()[i];
{ BaseClass *b = (*cd->baseclasses)[i];
if (b->base == this || isBaseOf2(b->base))
return 1;
@@ -870,7 +872,7 @@ int ClassDeclaration::isBaseInfoComplete()
if (!baseClass)
return ident == Id::Object;
for (size_t i = 0; i < baseclasses->dim; i++)
{ BaseClass *b = baseclasses->tdata()[i];
{ BaseClass *b = (*baseclasses)[i];
if (!b->base || !b->base->isBaseInfoComplete())
return 0;
}
@@ -908,7 +910,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
for (size_t i = 0; i < baseclasses->dim; i++)
{
BaseClass *b = baseclasses->tdata()[i];
BaseClass *b = (*baseclasses)[i];
if (b->base)
{
@@ -1001,9 +1003,11 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
//printf("\t[%d] = %s\n", i, fd->toChars());
if (ident == fd->ident &&
fd->type->covariant(tf) == 1)
{ //printf("fd->parent->isClassDeclaration() = %p", fd->parent->isClassDeclaration());
{ //printf("fd->parent->isClassDeclaration() = %p\n", fd->parent->isClassDeclaration());
if (!fdmatch)
goto Lfd;
if (fd == fdmatch)
goto Lfdmatch;
{
// Function type matcing: exact > covariant
@@ -1100,7 +1104,7 @@ int ClassDeclaration::isAbstract()
return TRUE;
for (size_t i = 1; i < vtbl.dim; i++)
{
FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
FuncDeclaration *fd = vtbl[i]->isFuncDeclaration();
//printf("\tvtbl[%d] = %p\n", i, fd);
if (!fd || fd->isAbstract())
@@ -1213,7 +1217,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
// Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; )
{ BaseClass *b = (*baseclasses)[0];
{ BaseClass *b = (*baseclasses)[i];
b->type = b->type->semantic(loc, sc);
Type *tb = b->type->toBasetype();
@@ -1238,7 +1242,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
BaseClass *b;
Type *tb;
b = baseclasses->tdata()[i];
b = (*baseclasses)[i];
b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype();
if (tb->ty == Tclass)
@@ -1256,7 +1260,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
// Check for duplicate interfaces
for (size_t j = 0; j < i; j++)
{
BaseClass *b2 = baseclasses->tdata()[j];
BaseClass *b2 = (*baseclasses)[j];
if (b2->base == tc->sym)
error("inherits from duplicate interface %s", b2->base->toChars());
}
@@ -1288,7 +1292,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
}
interfaces_dim = baseclasses->dim;
interfaces = (BaseClass **)baseclasses->data;
interfaces = baseclasses->tdata();
interfaceSemantic(sc);
@@ -1313,7 +1317,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
{
vtbl.reserve(d - 1);
for (size_t j = 1; j < d; j++)
vtbl.push((Dsymbol *)b->base->vtbl.data[j]);
vtbl.push(b->base->vtbl[j]);
}
}
else
@@ -1336,7 +1340,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
sc->parent = this;
if (isCOMinterface())
sc->linkage = LINKwindows;
sc->structalign = 8;
sc->structalign = STRUCTALIGN_DEFAULT;
sc->protection = PROTpublic;
sc->explicitProtection = 0;
structalign = sc->structalign;
@@ -1438,7 +1442,7 @@ int InterfaceDeclaration::isBaseInfoComplete()
{
assert(!baseClass);
for (size_t i = 0; i < baseclasses->dim; i++)
{ BaseClass *b = baseclasses->tdata()[i];
{ BaseClass *b = (*baseclasses)[i];
if (!b->base || !b->base->isBaseInfoComplete ())
return 0;
}
@@ -1522,7 +1526,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins
// first entry is ClassInfo reference
for (size_t j = base->vtblOffset(); j < base->vtbl.dim; j++)
{
FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
FuncDeclaration *ifd = base->vtbl[j]->isFuncDeclaration();
FuncDeclaration *fd;
TypeFunction *tf;
@@ -1559,7 +1563,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins
fd = NULL;
}
if (vtbl)
vtbl->data[j] = fd;
(*vtbl)[j] = fd;
}
return result;

View File

@@ -10,6 +10,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h> // strcmp()
#include "id.h"
#include "init.h"
@@ -266,7 +267,14 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc);
sc->pop();
e = e->optimize(WANTvalue | WANTinterpret);
if (!e->type->checkBoolean())
{
if (e->type->toBasetype() != Type::terror)
exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
inc = 0;
return 0;
}
e = e->ctfeInterpret();
--nest;
if (e->op == TOKerror)
{ exp = e;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // mem{cpy|set|cmp}()
#include <math.h>
#if __DMC__
@@ -1158,7 +1159,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
assert(sd);
Expressions *elements = new Expressions;
for (size_t i = 0; i < sd->fields.dim; i++)
{ Dsymbol *s = sd->fields.tdata()[i];
{ Dsymbol *s = sd->fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v);
@@ -1242,7 +1243,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
}
else if (e1->op == TOKarrayliteral)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
e = ale->elements->tdata()[i];
e = (*ale->elements)[i];
e->type = type;
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
@@ -1260,7 +1261,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
e = new ErrorExp();
}
else
{ e = ale->elements->tdata()[i];
{ e = (*ale->elements)[i];
e->type = type;
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
@@ -1275,12 +1276,12 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
for (size_t i = ae->keys->dim; i;)
{
i--;
Expression *ekey = ae->keys->tdata()[i];
Expression *ekey = (*ae->keys)[i];
Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2);
if (ex == EXP_CANT_INTERPRET)
return ex;
if (ex->isBool(TRUE))
{ e = ae->values->tdata()[i];
{ e = (*ae->values)[i];
e->type = type;
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
@@ -1351,7 +1352,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
elements->setDim(iupr - ilwr);
memcpy(elements->tdata(),
es1->elements->tdata() + ilwr,
(iupr - ilwr) * sizeof(es1->elements->tdata()[0]));
(iupr - ilwr) * sizeof((*es1->elements)[0]));
e = new ArrayLiteralExp(e1->loc, elements);
e->type = type;
}
@@ -1380,7 +1381,7 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *n
assert(0);
break;
}
existingAE->elements->tdata()[j+firstIndex]
(*existingAE->elements)[j+firstIndex]
= new IntegerExp(newval->loc, val, elemType);
}
}
@@ -1393,7 +1394,7 @@ void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *n
unsigned char *s = (unsigned char *)existingSE->string;
for (size_t j = 0; j < newae->elements->dim; j++)
{
unsigned value = (unsigned)(newae->elements->tdata()[j]->toInteger());
unsigned value = (unsigned)((*newae->elements)[j]->toInteger());
switch (existingSE->sz)
{
case 1: s[j+firstIndex] = value; break;
@@ -1417,6 +1418,48 @@ void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int f
memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len);
}
/* Compare a string slice with another string slice.
* Conceptually equivalent to memcmp( se1[lo1..lo1+len], se2[lo2..lo2+len])
*/
int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len)
{
unsigned char *s1 = (unsigned char *)se1->string;
unsigned char *s2 = (unsigned char *)se2->string;
size_t sz = se1->sz;
assert(sz == se2->sz);
return memcmp(s1 + sz * lo1, s2 + sz * lo2, sz * len);
}
/* Compare a string slice with an array literal slice
* Conceptually equivalent to memcmp( se1[lo1..lo1+len], ae2[lo2..lo2+len])
*/
int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len)
{
unsigned char *s = (unsigned char *)se1->string;
size_t sz = se1->sz;
int c = 0;
for (size_t j = 0; j < len; j++)
{
unsigned value = (unsigned)((*ae2->elements)[j + lo2]->toInteger());
unsigned svalue;
switch (sz)
{
case 1: svalue = s[j + lo1]; break;
case 2: svalue = ((unsigned short *)s)[j+lo1]; break;
case 4: svalue = ((unsigned *)s)[j + lo1]; break;
default:
assert(0);
}
int c = svalue - value;
if (c)
return c;
}
return 0;
}
/* Also return EXP_CANT_INTERPRET if this fails
*/
Expression *Cat(Type *type, Expression *e1, Expression *e2)
@@ -1534,7 +1577,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
elems->setDim(len);
for (size_t i= 0; i < ea->elements->dim; ++i)
{
elems->tdata()[i] = ea->elements->tdata()[i];
(*elems)[i] = (*ea->elements)[i];
}
ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems);
dest->type = type;
@@ -1552,7 +1595,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
elems->setDim(len);
for (size_t i= 0; i < ea->elements->dim; ++i)
{
elems->tdata()[es->len + i] = ea->elements->tdata()[i];
(*elems)[es->len + i] = (*ea->elements)[i];
}
ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems);
dest->type = type;

View File

@@ -92,6 +92,7 @@ enum PROT Declaration::prot()
*/
#if DMDV2
void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
{
if (sc->incontract && isParameter())
@@ -100,40 +101,10 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
if (sc->incontract && isResult())
error(loc, "cannot modify result '%s' in contract", toChars());
if (isCtorinit() && !t->isMutable())
if (isCtorinit() && !t->isMutable() ||
(storage_class & STCnodefaultctor))
{ // It's only modifiable if inside the right constructor
Dsymbol *s = sc->func;
while (1)
{
FuncDeclaration *fd = NULL;
if (s)
fd = s->isFuncDeclaration();
if (fd &&
((fd->isCtorDeclaration() && storage_class & STCfield) ||
(fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
fd->toParent2() == toParent()
)
{
VarDeclaration *v = isVarDeclaration();
assert(v);
v->ctorinit = 1;
//printf("setting ctorinit\n");
}
else
{
if (s)
{ s = s->toParent2();
continue;
}
else
{
const char *p = isStatic() ? "static " : "";
error(loc, "can only initialize %sconst %s inside %sconstructor",
p, toChars(), p);
}
}
break;
}
modifyFieldVar(loc, sc, isVarDeclaration(), NULL);
}
else
{
@@ -145,6 +116,8 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
p = "const";
else if (isImmutable())
p = "immutable";
else if (isWild())
p = "inout";
else if (storage_class & STCmanifest)
p = "enum";
else if (!t->isAssignable())
@@ -205,12 +178,13 @@ Type *TupleDeclaration::getType()
/* We know it's a type tuple, so build the TypeTuple
*/
Types *types = (Types *)objects;
Parameters *args = new Parameters();
args->setDim(objects->dim);
OutBuffer buf;
int hasdeco = 1;
for (size_t i = 0; i < objects->dim; i++)
{ Type *t = (Type *)objects->data[i];
for (size_t i = 0; i < types->dim; i++)
{ Type *t = (*types)[i];
//printf("type = %s\n", t->toChars());
#if 0
@@ -351,7 +325,7 @@ void TypedefDeclaration::semantic2(Scope *sc)
{
Initializer *savedinit = init;
int errors = global.errors;
init = init->semantic(sc, basetype, WANTinterpret);
init = init->semantic(sc, basetype, INITinterpret);
if (errors != global.errors)
{
init = savedinit;
@@ -538,6 +512,18 @@ void AliasDeclaration::semantic(Scope *sc)
else if (t)
{
type = t->semantic(loc, sc);
/* If type is class or struct, convert to symbol.
* See bugzilla 6475.
*/
s = type->toDsymbol(sc);
if (s
#if DMDV2
&& ((s->getType() && type->equals(s->getType())) || s->isEnumMember())
#endif
)
goto L2;
//printf("\talias resolved to type %s\n", type->toChars());
}
if (overnext)
@@ -658,7 +644,9 @@ Dsymbol *AliasDeclaration::toAlias()
aliassym = new AliasDeclaration(loc, ident, Type::terror);
type = Type::terror;
}
else if (!aliassym && scope)
else if (aliassym || type->deco)
; // semantic is already done.
else if (scope)
semantic(scope);
Dsymbol *s = aliassym ? aliassym->toAlias() : this;
return s;
@@ -846,9 +834,32 @@ void VarDeclaration::semantic(Scope *sc)
//printf("storage_class = x%x\n", storage_class);
#if DMDV2
if (storage_class & STCgshared && global.params.safe && !sc->module->safe)
// Safety checks
if (sc->func && !sc->intypeof)
{
error("__gshared not allowed in safe mode; use shared");
if (storage_class & STCgshared)
{
if (sc->func->setUnsafe())
error("__gshared not allowed in safe functions; use shared");
}
if (init && init->isVoidInitializer() && type->hasPointers())
{
if (sc->func->setUnsafe())
error("void initializers for pointers not allowed in safe functions");
}
if (type->hasPointers() && type->toDsymbol(sc))
{
Dsymbol *s = type->toDsymbol(sc);
if (s)
{
AggregateDeclaration *ad2 = s->isAggregateDeclaration();
if (ad2 && ad2->hasUnions)
{
if (sc->func->setUnsafe())
error("unions containing pointers are not allowed in @safe functions");
}
}
}
}
#endif
@@ -1115,7 +1126,7 @@ void VarDeclaration::semantic(Scope *sc)
Expression *e = init->toExpression();
if (!e)
{
init = init->semantic(sc, type, 0); // Don't need to interpret
init = init->semantic(sc, type, INITnointerpret);
e = init->toExpression();
if (!e)
{ error("is not a static and cannot have static initializer");
@@ -1216,7 +1227,7 @@ void VarDeclaration::semantic(Scope *sc)
}
else
{
init = init->semantic(sc, type, WANTinterpret);
init = init->semantic(sc, type, INITinterpret);
if (fd && isConst() && !isStatic())
{ // Make it static
storage_class |= STCstatic;
@@ -1246,7 +1257,7 @@ void VarDeclaration::semantic(Scope *sc)
}
else if (si || ai)
{ i2 = init->syntaxCopy();
i2 = i2->semantic(sc, type, WANTinterpret);
i2 = i2->semantic(sc, type, INITinterpret);
}
inuse--;
if (global.endGagging(errors)) // if errors happened
@@ -1261,7 +1272,7 @@ void VarDeclaration::semantic(Scope *sc)
else if (ei)
{
if (isDataseg() || (storage_class & STCmanifest))
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
else
e = e->optimize(WANTvalue);
switch (e->op)
@@ -1349,7 +1360,7 @@ void VarDeclaration::semantic2(Scope *sc)
printf("type = %p\n", ei->exp->type);
}
#endif
init = init->semantic(sc, type, WANTinterpret);
init = init->semantic(sc, type, INITinterpret);
inuse--;
}
}
@@ -1429,7 +1440,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
unsigned memsize = t->size(loc); // size of member
unsigned memalignsize = t->alignsize(); // size of member for alignment purposes
unsigned memalign = t->memalign(alignment); // alignment boundaries
structalign_t memalign = t->memalign(alignment); // alignment boundaries
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign,
&ad->structsize, &ad->alignsize, isunion);

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -283,7 +283,7 @@ struct VarDeclaration : Declaration
#else
int nestedref; // referenced by a lexically nested function
#endif
unsigned short alignment;
structalign_t alignment;
int ctorinit; // it has been initialized in a ctor
int onstack; // 1: it has been allocated on the stack
// 2: on stack, run destructor anyway
@@ -702,6 +702,7 @@ struct FuncDeclaration : Declaration
Identifier *outId; // identifier for out statement
VarDeclaration *vresult; // variable corresponding to outId
LabelDsymbol *returnLabel; // where the return goes
Scope *scout; // out contract scope for vresult->semantic
DsymbolTable *localsymtab; // used to prevent symbols in different
// scopes from having the same name
@@ -779,7 +780,7 @@ struct FuncDeclaration : Declaration
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
int overrides(FuncDeclaration *fd);
int findVtblIndex(Array *vtbl, int dim);
int findVtblIndex(Dsymbols *vtbl, int dim);
int overloadInsert(Dsymbol *s);
FuncDeclaration *overloadExactMatch(Type *t, Module* from);
FuncDeclaration *overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, Module *from, int flags = 0);
@@ -821,6 +822,7 @@ struct FuncDeclaration : Declaration
FuncDeclaration *isUnique();
int needsClosure();
int hasNestedFrameRefs();
void buildResultVar();
Statement *mergeFrequire(Statement *);
Statement *mergeFensure(Statement *);
Parameters *getParameters(int *pvarargs);

View File

@@ -19,6 +19,10 @@
#include "rmem.h"
#include "root.h"
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#include "gnuc.h"
#endif
#include "mars.h"
#include "dsymbol.h"
#include "macro.h"
@@ -77,7 +81,9 @@ struct DocComment
Macro **pmacrotable;
Escape **pescapetable;
DocComment();
DocComment() :
summary(NULL), copyright(NULL), macros(NULL), pmacrotable(NULL), pescapetable(NULL)
{ }
static DocComment *parse(Scope *sc, Dsymbol *s, unsigned char *comment);
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen);
@@ -227,7 +233,7 @@ void Module::gendocfile()
// Override with the ddoc macro files from the command line
for (size_t i = 0; i < global.params.ddocfiles->dim; i++)
{
FileName f(global.params.ddocfiles->tdata()[i], 0);
FileName f((*global.params.ddocfiles)[i], 0);
File file(&f);
file.readv();
// BUG: convert file contents to UTF-8 before use
@@ -1014,11 +1020,6 @@ void EnumMember::toDocBuffer(OutBuffer *buf)
/********************************* DocComment *********************************/
DocComment::DocComment()
{
memset(this, 0, sizeof(DocComment));
}
DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment)
{
//printf("parse(%s): '%s'\n", s->toChars(), comment);
@@ -1780,7 +1781,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
int leadingBlank = 1;
int inCode = 0;
int inComment = 0; // in <!-- ... --> comment
//int inComment = 0; // in <!-- ... --> comment
unsigned iCodeStart; // start of code section
unsigned iLineStart = offset;

View File

@@ -607,7 +607,7 @@ void Dsymbol::error(const char *format, ...)
}
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
verror(loc, format, ap, kind(), toPrettyChars());
va_end(ap);
}
@@ -615,41 +615,10 @@ void Dsymbol::error(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
verror(loc, format, ap, kind(), toPrettyChars());
va_end(ap);
}
void Dsymbol::verror(Loc loc, const char *format, va_list ap)
{
if (!global.gag)
{
char *p = loc.toChars();
if (!*p)
p = locToChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "Error: ");
fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
vfprintf(stdmsg, format, ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
//halt();
}
else
{
global.gaggedErrors++;
}
global.errors++;
//fatal();
}
void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
{
if (!global.params.useDeprecated && isDeprecated())
@@ -1286,6 +1255,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
VoidInitializer *e = new VoidInitializer(0);
e->type = Type::tsize_t;
v->init = e;
v->storage_class |= STCctfe; // it's never a true static variable
}
*pvar = v;
}

View File

@@ -152,7 +152,6 @@ struct Dsymbol : Object
int isAnonymous();
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void error(const char *format, ...) IS_PRINTF(2);
void verror(Loc loc, const char *format, va_list ap);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule(); // module where declared
Module *getCompilationModule(); // possibly different for templates

View File

@@ -1114,12 +1114,12 @@ dump(0);
/***************************************
* Return !=0 if expression is an lvalue.
*/
#if DMDV2
int Expression::isLvalue()
{
return 0;
}
#endif
/*******************************
* Give error if we're not an lvalue.
@@ -1133,7 +1133,7 @@ Expression *Expression::toLvalue(Scope *sc, Expression *e)
else if (!loc.filename)
loc = e->loc;
error("%s is not an lvalue", e->toChars());
return this;
return new ErrorExp();
}
Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
@@ -1143,11 +1143,14 @@ Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
// See if this expression is a modifiable lvalue (i.e. not const)
#if DMDV2
if (type && (!type->isMutable() || !type->isAssignable()))
error("%s is not mutable", e->toChars());
{ error("%s is not mutable", e->toChars());
return new ErrorExp();
}
#endif
return toLvalue(sc, e);
}
/************************************
* Detect cases where pointers to the stack can 'escape' the
* lifetime of the stack frame.
@@ -1916,16 +1919,17 @@ char *ComplexExp::toChars()
{
char buffer[sizeof(value) * 3 + 8 + 1];
#ifdef IN_GCC
char buf1[sizeof(value) * 3 + 8 + 1];
char buf2[sizeof(value) * 3 + 8 + 1];
#ifdef IN_GCC
creall(value).format(buf1, sizeof(buf1));
cimagl(value).format(buf2, sizeof(buf2));
sprintf(buffer, "(%s+%si)", buf1, buf2);
#else
sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
assert(strlen(buffer) < sizeof(buffer));
ld_sprint(buf1, 'g', creall(value));
ld_sprint(buf2, 'g', cimagl(value));
#endif
sprintf(buffer, "(%s+%si)", buf1, buf2);
assert(strlen(buffer) < sizeof(buffer));
return mem.strdup(buffer);
}
@@ -2126,12 +2130,12 @@ void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring(ident->toChars());
}
#if DMDV2
int IdentifierExp::isLvalue()
{
return 1;
}
#endif
Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
{
@@ -2180,7 +2184,7 @@ Lagain:
//printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
//printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
if (type)
if (type && !s->needThis())
return this;
if (!s->isFuncDeclaration()) // functions are checked after overloading
checkDeprecated(sc, s);
@@ -2356,6 +2360,24 @@ Lagain:
TupleDeclaration *tup = s->isTupleDeclaration();
if (tup)
{
for (size_t i = 0; i < tup->objects->dim; i++)
{
Dsymbol *sa = getDsymbol((*tup->objects)[i]);
if (sa && sa->needThis())
{
if (hasThis(sc)
#if DMDV2
&& !sa->isFuncDeclaration()
#endif
)
{
// Supply an implicit 'this', as in
// this.ident
(*tup->objects)[i] = new DotVarExp(loc, new ThisExp(loc), sa->isDeclaration());
}
}
}
e = new TupleExp(loc, tup);
e = e->semantic(sc);
return e;
@@ -2368,6 +2390,8 @@ Lagain:
s = ti->toAlias();
if (!s->isTemplateInstance())
goto Lagain;
if (ti->errors)
return new ErrorExp();
e = new ScopeExp(loc, ti);
e = e->semantic(sc);
return e;
@@ -2395,12 +2419,12 @@ void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring(s->toChars());
}
#if DMDV2
int DsymbolExp::isLvalue()
{
return 1;
}
#endif
Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
{
@@ -2493,12 +2517,12 @@ void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("this");
}
#if DMDV2
int ThisExp::isLvalue()
{
return 1;
}
#endif
Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
{
@@ -2917,12 +2941,15 @@ int StringExp::isBool(int result)
return result ? TRUE : FALSE;
}
#if DMDV2
int StringExp::isLvalue()
{
return 1;
/* string literal is rvalue in default, but
* conversion to reference of static array is only allowed.
*/
return 0;
}
#endif
unsigned StringExp::charAt(size_t i)
{ unsigned value;
@@ -3059,6 +3086,7 @@ ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
{
elements = new Expressions;
elements->push(e);
this->ownedByCtfe = false;
}
Expression *ArrayLiteralExp::syntaxCopy()
@@ -3121,7 +3149,9 @@ Expression *ArrayLiteralExp::semantic(Scope *sc)
/* Disallow array literals of type void being used.
*/
if (elements->dim > 0 && t0->ty == Tvoid)
error("%s of type %s has no value", toChars(), type->toChars());
{ error("%s of type %s has no value", toChars(), type->toChars());
return new ErrorExp();
}
return this;
}
@@ -3145,13 +3175,6 @@ int ArrayLiteralExp::isBool(int result)
return result ? (dim != 0) : (dim == 0);
}
#if DMDV2
int ArrayLiteralExp::canThrow()
{
return 1; // because it can fail allocating memory
}
#endif
StringExp *ArrayLiteralExp::toString()
{
TY telem = type->nextOf()->toBasetype()->ty;
@@ -3163,10 +3186,10 @@ StringExp *ArrayLiteralExp::toString()
if (elements)
for (int i = 0; i < elements->dim; ++i)
{
Expression *ch = elements->tdata()[i];
Expression *ch = (*elements)[i];
if (ch->op != TOKint64)
return NULL;
buf.writedchar(ch->toInteger());
buf.writeUTF8(ch->toInteger());
}
buf.writebyte(0);
@@ -3174,7 +3197,8 @@ StringExp *ArrayLiteralExp::toString()
if (telem == Twchar) prefix = 'w';
else if (telem == Tdchar) prefix = 'd';
StringExp *se = new StringExp(loc, buf.extractData(), buf.size - 1, prefix);
const size_t len = buf.offset - 1;
StringExp *se = new StringExp(loc, buf.extractData(), len, prefix);
se->type = type;
return se;
}
@@ -3193,7 +3217,7 @@ void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
size_t dim = elements ? elements->dim : 0;
buf->printf("A%u", dim);
for (size_t i = 0; i < dim; i++)
{ Expression *e = elements->tdata()[i];
{ Expression *e = (*elements)[i];
e->toMangleBuffer(buf);
}
}
@@ -3283,8 +3307,8 @@ void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writeByte('[');
for (size_t i = 0; i < keys->dim; i++)
{ Expression *key = (Expression *)keys->data[i];
Expression *value = (Expression *)values->data[i];
{ Expression *key = (*keys)[i];
Expression *value = (*values)[i];
if (i)
buf->writeByte(',');
@@ -3300,8 +3324,8 @@ void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
size_t dim = keys->dim;
buf->printf("A%u", dim);
for (size_t i = 0; i < dim; i++)
{ Expression *key = (Expression *)keys->data[i];
Expression *value = (Expression *)values->data[i];
{ Expression *key = (*keys)[i];
Expression *value = (*values)[i];
key->toMangleBuffer(buf);
value->toMangleBuffer(buf);
@@ -3323,6 +3347,7 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *
#endif
this->soffset = 0;
this->fillHoles = 1;
this->ownedByCtfe = false;
#if IN_LLVM
constType = NULL;
#endif
@@ -3411,7 +3436,7 @@ Expression *StructLiteralExp::semantic(Scope *sc)
else if (v->scope)
{ // Do deferred semantic analysis
Initializer *i2 = v->init->syntaxCopy();
i2 = i2->semantic(v->scope, v->type, WANTinterpret);
i2 = i2->semantic(v->scope, v->type, INITinterpret);
e = i2->toExpression();
// remove v->scope (see bug 3426)
// but not if gagged, for we might be called again.
@@ -3554,7 +3579,7 @@ void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
size_t dim = elements ? elements->dim : 0;
buf->printf("S%u", dim);
for (size_t i = 0; i < dim; i++)
{ Expression *e = (Expression *)elements->data[i];
{ Expression *e = (*elements)[i];
if (e)
e->toMangleBuffer(buf);
else
@@ -3641,6 +3666,8 @@ Lagain:
ti->semantic(sc);
if (ti->inst)
{
if (ti->inst->errors)
return new ErrorExp();
Dsymbol *s = ti->inst->toAlias();
sds2 = s->isScopeDsymbol();
if (!sds2)
@@ -4356,14 +4383,14 @@ void VarExp::checkEscapeRef()
}
}
#if DMDV2
int VarExp::isLvalue()
{
if (var->storage_class & STClazy)
return 0;
return 1;
}
#endif
Expression *VarExp::toLvalue(Scope *sc, Expression *e)
{
@@ -5505,6 +5532,11 @@ Expression *BinAssignExp::semantic(Scope *sc)
return this;
}
int BinAssignExp::isLvalue()
{
return 1;
}
/************************************************************/
CompileExp::CompileExp(Loc loc, Expression *e)
@@ -5526,7 +5558,7 @@ Expression *CompileExp::semantic(Scope *sc)
error("argument to mixin must be a string type, not %s\n", e1->type->toChars());
return new ErrorExp();
}
e1 = e1->optimize(WANTvalue | WANTinterpret);
e1 = e1->ctfeInterpret();
StringExp *se = e1->toString();
if (!se)
{ error("argument to mixin must be a string, not (%s)", e1->toChars());
@@ -5566,7 +5598,7 @@ Expression *FileExp::semantic(Scope *sc)
#endif
UnaExp::semantic(sc);
e1 = resolveProperties(sc, e1);
e1 = e1->optimize(WANTvalue | WANTinterpret);
e1 = e1->ctfeInterpret();
if (e1->op != TOKstring)
{ error("file name argument must be a string, not (%s)", e1->toChars());
goto Lerror;
@@ -6166,12 +6198,12 @@ Expression *DotVarExp::semantic(Scope *sc)
return this;
}
#if DMDV2
int DotVarExp::isLvalue()
{
return 1;
}
#endif
Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
{
@@ -7272,17 +7304,23 @@ int CallExp::canThrow()
}
#endif
#if DMDV2
int CallExp::isLvalue()
{
// if (type->toBasetype()->ty == Tstruct)
// return 1;
Type *tb = e1->type->toBasetype();
if (tb->ty == Tdelegate || tb->ty == Tpointer)
tb = tb->nextOf();
#if DMDV2
if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
{
if (e1->op == TOKdotvar)
if (((DotVarExp *)e1)->var->isCtorDeclaration())
return 0;
return 1; // function returns a reference
}
#endif
return 0;
}
#endif
Expression *CallExp::toLvalue(Scope *sc, Expression *e)
{
@@ -7478,12 +7516,12 @@ Expression *PtrExp::semantic(Scope *sc)
return this;
}
#if DMDV2
int PtrExp::isLvalue()
{
return 1;
}
#endif
void PtrExp::checkEscapeRef()
{
@@ -8014,8 +8052,8 @@ Expression *SliceExp::semantic(Scope *sc)
if (t->ty == Ttuple)
{
lwr = lwr->optimize(WANTvalue | WANTinterpret);
upr = upr->optimize(WANTvalue | WANTinterpret);
lwr = lwr->ctfeInterpret();
upr = upr->ctfeInterpret();
uinteger_t i1 = lwr->toUInteger();
uinteger_t i2 = upr->toUInteger();
@@ -8098,12 +8136,12 @@ void SliceExp::checkEscapeRef()
e1->checkEscapeRef();
}
#if DMDV2
int SliceExp::isLvalue()
{
return 1;
}
#endif
Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
{
@@ -8199,6 +8237,8 @@ Expression *ArrayExp::semantic(Scope *sc)
#endif
UnaExp::semantic(sc);
e1 = resolveProperties(sc, e1);
if (e1->op == TOKerror)
return e1;
t1 = e1->type->toBasetype();
if (t1->ty != Tclass && t1->ty != Tstruct)
@@ -8207,13 +8247,13 @@ Expression *ArrayExp::semantic(Scope *sc)
{ error("only one index allowed to index %s", t1->toChars());
goto Lerr;
}
e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
e = new IndexExp(loc, e1, (*arguments)[0]);
return e->semantic(sc);
}
// Run semantic() on each argument
for (size_t i = 0; i < arguments->dim; i++)
{ e = (Expression *)arguments->data[i];
{ e = (*arguments)[i];
e = e->semantic(sc);
if (!e->type)
@@ -8222,7 +8262,7 @@ Expression *ArrayExp::semantic(Scope *sc)
}
else if (e->type == Type::terror)
goto Lerr;
arguments->data[i] = (void *)e;
(*arguments)[i] = e;
}
expandTuples(arguments);
@@ -8239,14 +8279,14 @@ Lerr:
return new ErrorExp();
}
#if DMDV2
int ArrayExp::isLvalue()
{
if (type && type->toBasetype()->ty == Tvoid)
return 0;
return 1;
}
#endif
Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
{
@@ -8328,12 +8368,12 @@ void CommaExp::checkEscapeRef()
e2->checkEscapeRef();
}
#if DMDV2
int CommaExp::isLvalue()
{
return e2->isLvalue();
}
#endif
Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
{
@@ -8510,12 +8550,12 @@ Lerr:
return new ErrorExp();
}
#if DMDV2
int IndexExp::isLvalue()
{
return 1;
}
#endif
Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
{
@@ -10514,12 +10554,12 @@ Expression *CondExp::semantic(Scope *sc)
return this;
}
#if DMDV2
int CondExp::isLvalue()
{
return e1->isLvalue() && e2->isLvalue();
}
#endif
Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
{

View File

@@ -136,6 +136,7 @@ struct Expression : Object
virtual StringExp *toString();
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toMangleBuffer(OutBuffer *buf);
virtual int isLvalue();
virtual Expression *toLvalue(Scope *sc, Expression *e);
virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
virtual Expression *implicitCastTo(Scope *sc, Type *t);
@@ -164,6 +165,11 @@ struct Expression : Object
// Same as WANTvalue, but also expand variables as far as possible
#define WANTexpand 8
// Entry point for CTFE.
// A compile-time result is required. Give an error if not possible
Expression *ctfeInterpret();
// Implementation of CTFE for this expression
virtual Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
virtual int isConst();
@@ -313,6 +319,7 @@ struct IdentifierExp : Expression
char *toChars();
void dump(int indent);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
@@ -331,6 +338,7 @@ struct DsymbolExp : Expression
char *toChars();
void dump(int indent);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
@@ -343,6 +351,7 @@ struct ThisExp : Expression
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
int inlineCost3(InlineCostState *ics);
@@ -415,6 +424,7 @@ struct StringExp : Expression
Expression *castTo(Scope *sc, Type *t);
int compare(Object *obj);
int isBool(int result);
int isLvalue();
unsigned charAt(size_t i);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
@@ -915,9 +925,10 @@ struct BinExp : Expression
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *));
Expression *interpretCommon2(InterState *istate, CtfeGoal goal,
Expression *(*fp)(TOK, Type *, Expression *, Expression *));
Expression *(*fp)(Loc, TOK, Type *, Expression *, Expression *));
Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
Expression *interpretFourPointerRelation(InterState *istate, CtfeGoal goal);
Expression *arrayOp(Scope *sc);
Expression *doInline(InlineDoState *ids);
@@ -938,6 +949,7 @@ struct BinAssignExp : BinExp
}
Expression *semantic(Scope *sc);
int isLvalue();
};
/****************************************************************/
@@ -1004,6 +1016,7 @@ struct DotVarExp : UnaExp
DotVarExp(Loc loc, Expression *e, Declaration *var);
Expression *semantic(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
Expression *optimize(int result);
@@ -1091,6 +1104,7 @@ struct CallExp : UnaExp
#if IN_DMD
elem *toElem(IRState *irs);
#endif
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -1130,6 +1144,7 @@ struct PtrExp : UnaExp
PtrExp(Loc loc, Expression *e);
PtrExp(Loc loc, Expression *e, Type *t);
Expression *semantic(Scope *sc);
int isLvalue();
void checkEscapeRef();
Expression *toLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -1285,6 +1300,7 @@ struct SliceExp : UnaExp
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
@@ -1334,6 +1350,7 @@ struct ArrayExp : UnaExp
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -1359,6 +1376,7 @@ struct CommaExp : BinExp
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
@@ -1382,6 +1400,7 @@ struct IndexExp : BinExp
IndexExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -1921,6 +1940,7 @@ struct CondExp : BinExp
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void checkEscapeRef();
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
Expression *checkToBoolean();
@@ -2036,5 +2056,8 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *n
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex);
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex);
int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len);
int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len);
#endif /* DMD_EXPRESSION_H */

View File

@@ -47,6 +47,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
outId = NULL;
vresult = NULL;
returnLabel = NULL;
scout = NULL;
fensure = NULL;
fbody = NULL;
localsymtab = NULL;
@@ -436,9 +437,6 @@ void FuncDeclaration::semantic(Scope *sc)
break;
if (!this->parent->isClassDeclaration() // if both are mixins then error
#if !BREAKABI
&& !isDtorDeclaration()
#endif
#if DMDV2
&& !isPostBlitDeclaration()
#endif
@@ -484,7 +482,7 @@ void FuncDeclaration::semantic(Scope *sc)
for (int i = 0; i < cd->interfaces_dim; i++)
{
BaseClass *b = cd->interfaces[i];
vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
vi = findVtblIndex((Dsymbols *)&b->base->vtbl, b->base->vtbl.dim);
switch (vi)
{
case -1:
@@ -671,7 +669,7 @@ void FuncDeclaration::semantic(Scope *sc)
fdrequire = fd;
}
if (!outId && f->nextOf()->toBasetype()->ty != Tvoid)
if (!outId && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid)
outId = Id::result; // provide a default
if (fensure)
@@ -771,6 +769,12 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
if (!fbody && inferRetType && !type->nextOf())
{
error("has no function body with return type inference");
return;
}
if (frequire)
{
for (int i = 0; i < foverrides.dim; i++)
@@ -813,7 +817,7 @@ void FuncDeclaration::semantic3(Scope *sc)
STCproperty | STCsafe | STCtrusted | STCsystem);
sc2->protection = PROTpublic;
sc2->explicitProtection = 0;
sc2->structalign = 8;
sc2->structalign = STRUCTALIGN_DEFAULT;
sc2->incontract = 0;
sc2->enclosingFinally = NULL;
sc2->enclosingScopeExit = NULL;
@@ -887,7 +891,6 @@ void FuncDeclaration::semantic3(Scope *sc)
if (f->linkage == LINKd)
{ // Declare _arguments[]
#if BREAKABI
v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
v_arguments->storage_class = STCparameter | STCin;
v_arguments->semantic(sc2);
@@ -899,14 +902,6 @@ void FuncDeclaration::semantic3(Scope *sc)
_arguments->semantic(sc2);
sc2->insert(_arguments);
_arguments->parent = this;
#else
t = Type::typeinfo->type->arrayOf();
v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL);
v_arguments->storage_class = STCparameter | STCin;
v_arguments->semantic(sc2);
sc2->insert(v_arguments);
v_arguments->parent = this;
#endif
}
if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
{ // Declare _argptr
@@ -1010,7 +1005,7 @@ void FuncDeclaration::semantic3(Scope *sc)
if (f->parameters)
{
for (size_t i = 0; i < f->parameters->dim; i++)
{ Parameter *arg = (Parameter *)f->parameters->data[i];
{ Parameter *arg = (*f->parameters)[i];
if (!arg->ident)
continue; // never used, so ignore
@@ -1025,7 +1020,7 @@ void FuncDeclaration::semantic3(Scope *sc)
VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration();
assert(v);
Expression *e = new VarExp(v->loc, v);
exps->data[j] = (void *)e;
(*exps)[j] = e;
}
assert(arg->ident);
TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
@@ -1039,145 +1034,106 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
/* Do the semantic analysis on the [in] preconditions and
* [out] postconditions.
*/
sc2->incontract++;
// Precondition invariant
Statement *fpreinv = NULL;
if (addPreInvariant())
{
Expression *e = NULL;
if (isDtorDeclaration())
{
// Call invariant directly only if it exists
InvariantDeclaration *inv = ad->inv;
ClassDeclaration *cd = ad->isClassDeclaration();
if (frequire)
{ /* frequire is composed of the [in] contracts
*/
// BUG: need to error if accessing out parameters
// BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
// BUG: verify that all in and ref parameters are read
frequire = frequire->semantic(sc2);
labtab = NULL; // so body can't refer to labels
while (!inv && cd)
{
cd = cd->baseClass;
if (!cd)
break;
inv = cd->inv;
}
if (inv)
{
e = new DsymbolExp(0, inv);
e = new CallExp(0, e);
e = e->semantic(sc2);
}
}
else
{ // Call invariant virtually
Expression *v = new ThisExp(0);
v->type = vthis->type;
#if STRUCTTHISREF
if (ad->isStructDeclaration())
v = v->addressOf(sc);
#endif
Expression *se = new StringExp(0, (char *)"null this");
se = se->semantic(sc);
se->type = Type::tchar->arrayOf();
e = new AssertExp(loc, v, se);
}
if (e)
fpreinv = new ExpStatement(0, e);
}
// Postcondition invariant
Statement *fpostinv = NULL;
if (addPostInvariant())
{
Expression *e = NULL;
if (isCtorDeclaration())
{
// Call invariant directly only if it exists
InvariantDeclaration *inv = ad->inv;
ClassDeclaration *cd = ad->isClassDeclaration();
while (!inv && cd)
{
cd = cd->baseClass;
if (!cd)
break;
inv = cd->inv;
}
if (inv)
{
e = new DsymbolExp(0, inv);
e = new CallExp(0, e);
e = e->semantic(sc2);
}
}
else
{ // Call invariant virtually
Expression *v = new ThisExp(0);
v->type = vthis->type;
#if STRUCTTHISREF
if (ad->isStructDeclaration())
v = v->addressOf(sc);
#endif
e = new AssertExp(0, v);
}
if (e)
fpostinv = new ExpStatement(0, e);
}
if (fensure || addPostInvariant())
{ /* fensure is composed of the [out] contracts
*/
if (!type->nextOf())
{ // Have to do semantic() on fbody first
error("post conditions are not supported if the return type is inferred");
return;
{
if ((fensure && global.params.useOut) || fpostinv)
{ returnLabel = new LabelDsymbol(Id::returnLabel);
}
// scope of out contract (need for vresult->semantic)
ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc2->scopesym;
scout = sc2->push(sym);
}
if (fbody)
{
ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc2->scopesym;
sc2 = sc2->push(sym);
assert(type->nextOf());
if (type->nextOf()->ty == Tvoid)
{
if (outId)
error("void functions have no result");
}
else
{
if (!outId)
outId = Id::result; // provide a default
}
if (outId)
{ // Declare result variable
VarDeclaration *v;
Loc loc = this->loc;
if (fensure)
loc = fensure->loc;
v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
v->noscope = 1;
#if DMDV2
if (!isVirtual())
v->storage_class |= STCconst;
if (f->isref)
{
v->storage_class |= STCref | STCforeach;
}
#endif
sc2->incontract--;
v->semantic(sc2);
sc2->incontract++;
if (!sc2->insert(v))
error("out result %s is already defined", v->toChars());
v->parent = this;
vresult = v;
// vresult gets initialized with the function return value
// in ReturnStatement::semantic()
}
// BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
if (fensure)
{ fensure = fensure->semantic(sc2);
labtab = NULL; // so body can't refer to labels
}
if (!global.params.useOut)
{ fensure = NULL; // discard
vresult = NULL;
}
// Postcondition invariant
if (addPostInvariant())
{
Expression *e = NULL;
if (isCtorDeclaration())
{
// Call invariant directly only if it exists
InvariantDeclaration *inv = ad->inv;
ClassDeclaration *cd = ad->isClassDeclaration();
while (!inv && cd)
{
cd = cd->baseClass;
if (!cd)
break;
inv = cd->inv;
}
if (inv)
{
e = new DsymbolExp(0, inv);
e = new CallExp(0, e);
e = e->semantic(sc2);
}
}
else
{ // Call invariant virtually
Expression *v = new ThisExp(0);
v->type = vthis->type;
#if STRUCTTHISREF
if (ad->isStructDeclaration())
v = v->addressOf(sc);
#endif
e = new AssertExp(0, v);
}
if (e)
{
ExpStatement *s = new ExpStatement(0, e);
if (fensure)
fensure = new CompoundStatement(0, s, fensure);
else
fensure = s;
}
}
if (fensure)
{ returnLabel = new LabelDsymbol(Id::returnLabel);
LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure);
returnLabel->statement = ls;
}
sc2 = sc2->pop();
}
sc2->incontract--;
if (fbody)
{ ClassDeclaration *cd = isClassMember();
ClassDeclaration *cd = isClassMember();
/* If this is a class constructor
*/
@@ -1220,7 +1176,7 @@ void FuncDeclaration::semantic3(Scope *sc)
}
else
{
for (int i = 0; i < ad->members->dim; i++)
for (size_t i = 0; i < ad->members->dim; i++)
{ Dsymbol *s = (Dsymbol *)ad->members->data[i];
s->checkCtorConstInit();
@@ -1235,7 +1191,7 @@ void FuncDeclaration::semantic3(Scope *sc)
// Verify that all the ctorinit fields got initialized
if (!(sc2->callSuper & CSXthis_ctor))
{
for (int i = 0; i < cd->fields.dim; i++)
for (size_t i = 0; i < cd->fields.dim; i++)
{ VarDeclaration *v = (VarDeclaration *)cd->fields.data[i];
if (v->ctorinit == 0 && v->isCtorinit())
@@ -1280,15 +1236,7 @@ void FuncDeclaration::semantic3(Scope *sc)
int offend = blockexit & BEfallthru;
#endif
if (type->nextOf()->ty == Tvoid)
{
if (offend && isMain())
{ // Add a return 0; statement
Statement *s = new ReturnStatement(0, new IntegerExp(0));
fbody = new CompoundStatement(0, fbody, s);
}
}
else
if (type->nextOf()->ty != Tvoid)
{
if (offend)
{ Expression *e;
@@ -1317,6 +1265,66 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
}
sc2 = sc2->pop();
}
Statement *freq = frequire;
Statement *fens = fensure;
/* Do the semantic analysis on the [in] preconditions and
* [out] postconditions.
*/
if (freq)
{ /* frequire is composed of the [in] contracts
*/
ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc2->scopesym;
sc2 = sc2->push(sym);
sc2->incontract++;
// BUG: need to error if accessing out parameters
// BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
// BUG: verify that all in and ref parameters are read
DsymbolTable *labtab_save = labtab;
labtab = NULL; // so in contract can't refer to out/body labels
freq = freq->semantic(sc2);
labtab = labtab_save;
sc2->incontract--;
sc2 = sc2->pop();
if (!global.params.useIn)
freq = NULL;
}
if (fens)
{ /* fensure is composed of the [out] contracts
*/
if (type->nextOf()->ty == Tvoid && outId)
{
error("void functions have no result");
}
if (type->nextOf()->ty != Tvoid)
buildResultVar();
sc2 = scout; //push
sc2->incontract++;
// BUG: need to treat parameters as const
// BUG: need to disallow returns and throws
DsymbolTable *labtab_save = labtab;
labtab = NULL; // so out contract can't refer to in/body labels
fens = fens->semantic(sc2);
labtab = labtab_save;
sc2->incontract--;
sc2 = sc2->pop();
if (!global.params.useOut)
fens = NULL;
}
{
@@ -1420,91 +1428,34 @@ void FuncDeclaration::semantic3(Scope *sc)
// Merge contracts together with body into one compound statement
if (frequire && global.params.useIn)
{ frequire->incontract = 1;
a->push(frequire);
}
// Precondition invariant
if (addPreInvariant())
if (freq || fpreinv)
{
Expression *e = NULL;
Expression *ee = NULL;
if (isDtorDeclaration())
{
// Call invariant directly only if it exists
InvariantDeclaration *inv = ad->inv;
ClassDeclaration *cd = ad->isClassDeclaration();
if (!freq)
freq = fpreinv;
else if (fpreinv)
freq = new CompoundStatement(0, freq, fpreinv);
while (!inv && cd)
{
cd = cd->baseClass;
if (!cd)
break;
inv = cd->inv;
}
if (inv)
{
e = new DsymbolExp(0, inv);
e = new CallExp(0, e);
e = e->semantic(sc2);
}
}
else
{ // Call invariant virtually
// LDC: unless this is a struct without invariant
StructDeclaration* sd = ad->isStructDeclaration();
if (!sd || sd->inv)
{
ThisExp *v = new ThisExp(0);
v->type = vthis->type;
e = new AssertExp(loc, v, NULL);
}
// LDC: check for null this
ThisExp* v = new ThisExp(0);
v->type = vthis->type;
#if STRUCTTHISREF
if (ad->isStructDeclaration())
v = v->addressOf(sc);
#endif
v->var = vthis;
NullExp *nv = new NullExp(0);
nv->type = v->type;
IdentityExp *ie = new IdentityExp(TOKnotidentity, 0, v, nv);
ie->type = Type::tbool;
Expression *se = new StringExp(0, (char *)"null this");
se = se->semantic(sc);
se->type = Type::tchar->arrayOf();
ee = new AssertExp(loc, ie, se);
}
if (ee)
{
ExpStatement *s = new ExpStatement(0, ee);
a->push(s);
}
if (e)
{
ExpStatement *s = new ExpStatement(0, e);
a->push(s);
}
freq->incontract = 1;
a->push(freq);
}
if (fbody)
a->push(fbody);
if (fensure)
if (fens || fpostinv)
{
if (!fens)
fens = fpostinv;
else if (fpostinv)
fens = new CompoundStatement(0, fpostinv, fens);
LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fens);
returnLabel->statement = ls;
a->push(returnLabel->statement);
if (type->nextOf()->ty != Tvoid)
if (type->nextOf()->ty != Tvoid && vresult)
{
// Create: return vresult;
assert(vresult);
Expression *e = new VarExp(0, vresult);
if (tintro)
{ e = e->implicitCastTo(sc, tintro->nextOf());
@@ -1514,6 +1465,11 @@ void FuncDeclaration::semantic3(Scope *sc)
a->push(s);
}
}
if (isMain() && type->nextOf()->ty == Tvoid)
{ // Add a return 0; statement
Statement *s = new ReturnStatement(0, new IntegerExp(0));
a->push(s);
}
fbody = new CompoundStatement(0, a);
#if DMDV2
@@ -1522,7 +1478,7 @@ void FuncDeclaration::semantic3(Scope *sc)
if (parameters)
{ for (size_t i = 0; i < parameters->dim; i++)
{
VarDeclaration *v = (VarDeclaration *)parameters->data[i];
VarDeclaration *v = (*parameters)[i];
if (v->storage_class & (STCref | STCout))
continue;
@@ -1649,6 +1605,48 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
}
/****************************************************
* Declare result variable lazily.
*/
void FuncDeclaration::buildResultVar()
{
if (vresult)
return;
assert(type->nextOf());
assert(type->nextOf()->toBasetype()->ty != Tvoid);
TypeFunction *tf = (TypeFunction *)(type);
Loc loc = this->loc;
if (fensure)
loc = fensure->loc;
if (!outId)
outId = Id::result; // provide a default
VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
v->noscope = 1;
v->storage_class |= STCresult;
#if DMDV2
if (!isVirtual())
v->storage_class |= STCconst;
if (tf->isref)
{
v->storage_class |= STCref | STCforeach;
}
#endif
v->semantic(scout);
if (!scout->insert(v))
error("out result %s is already defined", v->toChars());
v->parent = this;
vresult = v;
// vresult gets initialized with the function return value
// in ReturnStatement::semantic()
}
/****************************************************
* Merge into this function the 'in' contracts of all it overrides.
* 'in's are OR'd together, i.e. only one of them needs to pass.
@@ -1674,7 +1672,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf)
*/
for (int i = 0; i < foverrides.dim; i++)
{
FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
FuncDeclaration *fdv = foverrides[i];
/* The semantic pass on the contracts of the overridden functions must
* be completed before code generation occurs (bug 3602).
@@ -1729,7 +1727,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf)
*/
for (int i = 0; i < foverrides.dim; i++)
{
FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
FuncDeclaration *fdv = foverrides[i];
/* The semantic pass on the contracts of the overridden functions must
* be completed before code generation occurs (bug 3602 and 5230).
@@ -1796,17 +1794,31 @@ int FuncDeclaration::overrides(FuncDeclaration *fd)
* -2 can't determine because of forward references
*/
int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
{
FuncDeclaration *mismatch = NULL;
int exactvi = -1;
int bestvi = -1;
for (int vi = 0; vi < dim; vi++)
{
FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
FuncDeclaration *fdv = (*vtbl)[vi]->isFuncDeclaration();
if (fdv && fdv->ident == ident)
{
if (type->equals(fdv->type)) // if exact match
return vi; // no need to look further
{
if (fdv->parent->isClassDeclaration())
return vi; // no need to look further
if (exactvi >= 0)
{
error("cannot determine overridden function");
return exactvi;
}
exactvi = vi;
bestvi = vi;
continue;
}
int cov = type->covariant(fdv->type);
//printf("\tbaseclass cov = %d\n", cov);
@@ -3079,14 +3091,8 @@ char *DtorDeclaration::toChars()
int DtorDeclaration::isVirtual()
{
/* This should be FALSE so that dtor's don't get put into the vtbl[],
* but doing so will require recompiling everything.
*/
#if BREAKABI
// FALSE so that dtor's don't get put into the vtbl[]
return FALSE;
#else
return FuncDeclaration::isVirtual();
#endif
}
void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// initial header generation implementation by Dave Fladebo
// http://www.digitalmars.com
@@ -8,6 +8,7 @@
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <string.h> // memset()
struct HdrGenState
{

View File

@@ -98,8 +98,18 @@ void Import::load(Scope *sc)
if (s->isModule())
mod = (Module *)s;
else
{
if (pkg)
{
::error(loc, "can only import from a module, not from package %s.%s",
pkg->toPrettyChars(), id->toChars());
}
else
{
::error(loc, "can only import from a module, not from package %s",
id->toChars());
}
}
#endif
}
@@ -374,26 +384,24 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
}
buf->printf("%s", id->toChars());
if (names.dim > 0) {
buf->writebyte(':');
if (names.dim)
{
buf->writestring(" : ");
for (size_t i = 0; i < names.dim; i++)
{
if (i > 0) {
buf->writebyte(',');
}
Identifier *name = names[i];
Identifier *alias = aliases[i];
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias) {
if (alias)
buf->printf("%s = %s", alias->toChars(), name->toChars());
else
buf->printf("%s", name->toChars());
alias = name;
} else {
buf->printf("%s=%s", alias->toChars(), name->toChars());
}
if (i < names.dim - 1)
buf->writestring(", ");
}
}
buf->writebyte(';');
buf->printf(";");
buf->writenl();
}

View File

@@ -34,7 +34,7 @@ Initializer *Initializer::syntaxCopy()
return this;
}
Initializer *Initializer::semantic(Scope *sc, Type *t, int needInterpret)
Initializer *Initializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
return this;
}
@@ -87,7 +87,7 @@ Initializer *VoidInitializer::syntaxCopy()
}
Initializer *VoidInitializer::semantic(Scope *sc, Type *t, int needInterpret)
Initializer *VoidInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
//printf("VoidInitializer::semantic(t = %p)\n", t);
type = t;
@@ -144,7 +144,7 @@ void StructInitializer::addInit(Identifier *field, Initializer *value)
this->value.push(value);
}
Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
int errors = 0;
@@ -333,7 +333,12 @@ Expression *StructInitializer::toExpression()
if (unionSize == 1)
{ // Not a union -- default initialize if missing
if (!(*elements)[i])
(*elements)[i] = vd->type->defaultInit();
{ // Default initialize
if (vd->init)
(*elements)[i] = vd->init->toExpression();
else
(*elements)[i] = vd->type->defaultInit();
}
}
else
{ // anonymous union -- check for errors
@@ -433,7 +438,7 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value)
type = NULL;
}
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret)
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{ unsigned i;
unsigned length;
const unsigned amax = 0x80000000;
@@ -462,14 +467,39 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret)
Expression *idx = index[i];
if (idx)
{ idx = idx->semantic(sc);
idx = idx->optimize(WANTvalue | WANTinterpret);
idx = idx->ctfeInterpret();
index[i] = idx;
length = idx->toInteger();
}
Initializer *val = value[i];
ExpInitializer *ei = val->isExpInitializer();
if (ei && !idx)
ei->expandTuples = 1;
val = val->semantic(sc, t->nextOf(), needInterpret);
value[i] = val;
ei = val->isExpInitializer();
// found a tuple, expand it
if (ei && ei->exp->op == TOKtuple)
{
TupleExp *te = (TupleExp *)ei->exp;
index.remove(i);
value.remove(i);
for (size_t j = 0; j < te->exps->dim; ++j)
{
Expression *e = (*te->exps)[j];
index.insert(i + j, (Expression *)NULL);
value.insert(i + j, new ExpInitializer(e->loc, e));
}
i--;
continue;
}
else
{
value[i] = val;
}
length++;
if (length == 0)
{ error(loc, "array dimension overflow");
@@ -694,6 +724,7 @@ ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
: Initializer(loc)
{
this->exp = exp;
this->expandTuples = 0;
}
Initializer *ExpInitializer::syntaxCopy()
@@ -701,14 +732,18 @@ Initializer *ExpInitializer::syntaxCopy()
return new ExpInitializer(loc, exp->syntaxCopy());
}
Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
exp = exp->semantic(sc);
int wantOptimize = needInterpret ? WANTinterpret|WANTvalue : WANTvalue;
if (exp->op == TOKerror)
return this;
int olderrors = global.errors;
exp = exp->optimize(wantOptimize);
if (needInterpret)
exp = exp->ctfeInterpret();
else
exp = exp->optimize(WANTvalue);
if (!global.gag && olderrors != global.errors)
return this; // Failed, suppress duplicate error messages
@@ -716,6 +751,11 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
exp->error("initializer must be an expression, not '%s'", exp->toChars());
Type *tb = t->toBasetype();
if (exp->op == TOKtuple &&
expandTuples &&
!exp->implicitConvTo(t))
return new ExpInitializer(loc, exp);
/* Look for case of initializing a static array with a too-short
* string literal, such as:
* char[5] foo = "abc";
@@ -745,8 +785,13 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
}
exp = exp->implicitCastTo(sc, t);
if (exp->op == TOKerror)
return this;
L1:
exp = exp->optimize(wantOptimize);
if (needInterpret)
exp = exp->ctfeInterpret();
else
exp = exp->optimize(WANTvalue);
//printf("-ExpInitializer::semantic(): "); exp->print();
return this;
}

View File

@@ -28,6 +28,7 @@ struct ArrayInitializer;
struct ExpInitializer;
struct HdrGenState;
enum NeedInterpret { INITnointerpret, INITinterpret };
#if IN_LLVM
namespace llvm {
@@ -41,8 +42,7 @@ struct Initializer : Object
Initializer(Loc loc);
virtual Initializer *syntaxCopy();
// needInterpret is WANTinterpret if must be a manifest constant, 0 if not.
virtual Initializer *semantic(Scope *sc, Type *t, int needInterpret);
virtual Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
virtual Type *inferType(Scope *sc);
virtual Expression *toExpression() = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
@@ -66,7 +66,7 @@ struct VoidInitializer : Initializer
VoidInitializer(Loc loc);
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -88,7 +88,7 @@ struct StructInitializer : Initializer
StructInitializer(Loc loc);
Initializer *syntaxCopy();
void addInit(Identifier *field, Initializer *value);
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -113,7 +113,7 @@ struct ArrayInitializer : Initializer
ArrayInitializer(Loc loc);
Initializer *syntaxCopy();
void addInit(Expression *index, Initializer *value);
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Type *inferType(Scope *sc);
Expression *toExpression();
Initializer *toAssocArrayInitializer();
@@ -130,10 +130,11 @@ struct ArrayInitializer : Initializer
struct ExpInitializer : Initializer
{
Expression *exp;
int expandTuples;
ExpInitializer(Loc loc, Expression *exp);
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t, int needInterpret);
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Type *inferType(Scope *sc);
Expression *toExpression();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);

View File

@@ -14,6 +14,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // memset()
#include "id.h"
#include "init.h"

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -304,7 +304,7 @@ void Lexer::error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(tokenLoc(), format, ap);
::verror(tokenLoc(), format, ap);
va_end(ap);
}
@@ -312,34 +312,10 @@ void Lexer::error(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
::verror(loc, format, ap);
va_end(ap);
}
void Lexer::verror(Loc loc, const char *format, va_list ap)
{
if (mod && !global.gag)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
vfprintf(stdmsg, format, ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
if (global.errors >= 20) // moderate blizzard of cascading messages
fatal();
}
else
{
global.gaggedErrors++;
}
global.errors++;
}
TOK Lexer::nextToken()
{ Token *t;
@@ -669,7 +645,7 @@ void Lexer::scan(Token *t)
StringValue *sv = stringtable.update((char *)t->ptr, p - t->ptr);
Identifier *id = (Identifier *) sv->ptrvalue;
if (!id)
{ id = new Identifier(sv->lstring.string,TOKidentifier);
{ id = new Identifier(sv->toDchars(),TOKidentifier);
sv->ptrvalue = id;
}
t->ident = id;
@@ -1202,9 +1178,7 @@ void Lexer::scan(Token *t)
SINGLE(';', TOKsemicolon)
SINGLE(':', TOKcolon)
SINGLE('$', TOKdollar)
#if DMDV2
SINGLE('@', TOKat)
#endif
#undef SINGLE
#define DOUBLE(c1,tok1,c2,tok2) \
@@ -2629,8 +2603,9 @@ void Lexer::pragma()
{
p += 8;
filespec = mem.strdup(loc.filename ? loc.filename : mod->ident->toChars());
continue;
}
continue;
goto Lerr;
case '"':
if (filespec)
@@ -2913,7 +2888,7 @@ Identifier *Lexer::idPool(const char *s)
Identifier *id = (Identifier *) sv->ptrvalue;
if (!id)
{
id = new Identifier(sv->lstring.string, TOKidentifier);
id = new Identifier(sv->toDchars(), TOKidentifier);
sv->ptrvalue = id;
}
return id;
@@ -3091,7 +3066,7 @@ void Lexer::initKeywords()
{
unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]);
stringtable.init(1543);
stringtable.init(6151);
if (global.params.Dversion == 1)
nkeywords -= 2;
@@ -3104,7 +3079,7 @@ void Lexer::initKeywords()
const char *s = keywords[u].name;
enum TOK v = keywords[u].value;
StringValue *sv = stringtable.insert(s, strlen(s));
sv->ptrvalue = (void *) new Identifier(sv->lstring.string,v);
sv->ptrvalue = (void *) new Identifier(sv->toDchars(),v);
//printf("tochars[%d] = '%s'\n",v, s);
Token::tochars[v] = s;
@@ -3201,6 +3176,7 @@ void Lexer::initKeywords()
Token::tochars[TOKpow] = "^^";
Token::tochars[TOKpowass] = "^^=";
Token::tochars[TOKgoesto] = "=>";
Token::tochars[TOKpound] = "#";
#endif
// For debugging

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -155,6 +155,7 @@ enum TOK
TOKargTypes,
TOKref,
TOKmacro,
TOKat,
#if DMDV2
TOKtraits,
TOKoverloadset,
@@ -165,9 +166,11 @@ enum TOK
TOKline,
TOKfile,
TOKshared,
TOKat,
TOKpow,
TOKpowass,
TOKgoesto,
TOKvector,
TOKpound,
#endif
// LDC specific
@@ -305,7 +308,6 @@ struct Lexer
TOK inreal(Token *t);
void error(const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void verror(Loc loc, const char *format, va_list ap);
void pragma();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);

View File

@@ -13,8 +13,8 @@
#include <ctype.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#if IN_LLVM
#include <string>
#include <cstdarg>
#endif
@@ -70,10 +70,10 @@ Global::Global()
copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v1.074";
version = "v1.075";
ldc_version = "LDC trunk";
llvm_version = "LLVM "LDC_LLVM_VERSION_STRING;
global.structalign = 8;
global.structalign = STRUCTALIGN_DEFAULT;
// This should only be used as a global, so the other fields are
// automatically initialized to zero when the program is loaded.
@@ -164,7 +164,7 @@ void errorSupplemental(Loc loc, const char *format, ...)
va_end( ap );
}
void verror(Loc loc, const char *format, va_list ap)
void verror(Loc loc, const char *format, va_list ap, const char *p1, const char *p2)
{
if (!global.gag)
{
@@ -175,9 +175,22 @@ void verror(Loc loc, const char *format, va_list ap)
mem.free(p);
fprintf(stdmsg, "Error: ");
if (p1)
fprintf(stdmsg, "%s ", p1);
if (p2)
fprintf(stdmsg, "%s ", p2);
#if _MSC_VER
// MS doesn't recognize %zu format
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stdmsg, "%s", tmp.toChars());
#else
vfprintf(stdmsg, format, ap);
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
if (global.errors >= 20) // moderate blizzard of cascading messages
fatal();
//halt();
}
else

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -103,7 +103,6 @@ the target object file format:
#endif
#define DMDV2 0 // Version 2.0 features
#define BREAKABI 1 // 0 if not ready to break the ABI just yet
#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
#define SARRAYVALUE DMDV2 // static arrays are value types
@@ -316,15 +315,21 @@ struct Param
#endif
};
typedef unsigned structalign_t;
#define STRUCTALIGN_DEFAULT ~0 // magic value means "match whatever the underlying C compiler does"
// other values are all powers of 2
struct Global
{
const char *mars_ext;
const char *sym_ext;
const char *obj_ext;
#if IN_LLVM
const char *obj_ext_alt;
const char *ll_ext;
const char *bc_ext;
const char *s_ext;
#endif
const char *lib_ext;
const char *dll_ext;
const char *doc_ext; // for Ddoc generated files
@@ -336,7 +341,9 @@ struct Global
const char *written;
Strings *path; // Array of char*'s which form the import lookup path
Strings *filePath; // Array of char*'s which form the file import lookup path
int structalign;
structalign_t structalign; // default alignment for struct fields
const char *version;
char *ldc_version;
char *llvm_version;
@@ -506,7 +513,7 @@ typedef uint64_t StorageClass;
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(2);
void errorSupplemental(Loc loc, const char *format, ...);
void verror(Loc loc, const char *format, va_list);
void verror(Loc loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL);
void vwarning(Loc loc, const char *format, va_list);
void verrorSupplemental(Loc loc, const char *format, va_list);
#ifdef __GNUC__

View File

@@ -20,7 +20,7 @@
#include <malloc.h>
#endif
#if IN_GCC
#ifdef IN_GCC
#include "gdc_alloca.h"
#endif
@@ -51,6 +51,11 @@
#include "llvm/Support/CommandLine.h"
#include <map>
// stricmp
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
static llvm::cl::opt<bool> preservePaths("op",
llvm::cl::desc("Do not strip paths from source file"),
llvm::cl::ZeroOrMore);
@@ -319,7 +324,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
OutBuffer buf;
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = packages->tdata()[i];
{ Identifier *pid = (*packages)[i];
buf.writestring(pid->toChars());
#if _WIN32
@@ -380,7 +385,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
if (packages)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = packages->tdata()[i];
{ Identifier *pid = (*packages)[i];
printf("%s.", pid->toChars());
}
}
@@ -411,8 +416,8 @@ bool Module::read(Loc loc)
{
for (size_t i = 0; i < global.path->dim; i++)
{
char *p = global.path->tdata()[i];
fprintf(stdmsg, "import path[%zd] = %s\n", i, p);
char *p = (*global.path)[i];
fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p);
}
}
else
@@ -460,24 +465,17 @@ inline unsigned readlongBE(unsigned *p)
#if IN_LLVM
void Module::parse(bool gen_docs)
#elif IN_GCC
void Module::parse(bool dump_source)
#else
void Module::parse()
#endif
{ char *srcname;
unsigned char *buf;
unsigned buflen;
unsigned le;
unsigned bom;
{
//printf("Module::parse()\n");
srcname = srcfile->name->toChars();
char *srcname = srcfile->name->toChars();
//printf("Module::parse(srcname = '%s')\n", srcname);
buf = srcfile->buffer;
buflen = srcfile->len;
unsigned char *buf = srcfile->buffer;
unsigned buflen = srcfile->len;
if (buflen >= 2)
{
@@ -490,7 +488,8 @@ void Module::parse()
* EF BB BF UTF-8
*/
bom = 1; // assume there's a BOM
unsigned le;
unsigned bom = 1; // assume there's a BOM
if (buf[0] == 0xFF && buf[1] == 0xFE)
{
if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
@@ -641,7 +640,7 @@ void Module::parse()
#ifdef IN_GCC
// dump utf-8 encoded source
if (dump_source)
if (global.params.dump_source)
{ // %% srcname could contain a path ...
d_gcc_dump_source(srcname, "utf-8", buf, buflen);
}
@@ -665,7 +664,7 @@ void Module::parse()
buflen = dbuf->offset;
#ifdef IN_GCC
// dump extracted source
if (dump_source)
if (global.params.dump_source)
d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
#endif
}
@@ -767,7 +766,7 @@ void Module::importAll(Scope *prevsc)
symtab = new DsymbolTable();
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
s->addMember(NULL, sc->scopesym, 1);
}
}
@@ -780,13 +779,13 @@ void Module::importAll(Scope *prevsc)
*/
setScope(sc); // remember module scope for semantic
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
s->setScope(sc);
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
s->importAll(sc);
}
@@ -841,7 +840,7 @@ void Module::semantic()
// Do semantic() on members that don't depend on others
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
//printf("\tModule('%s'): '%s'.semantic0()\n", toChars(), s->toChars());
s->semantic0(sc);
@@ -849,7 +848,7 @@ void Module::semantic()
// Pass 1 semantic routines: do public side of the definition
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
//printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
s->semantic(sc);
@@ -870,7 +869,7 @@ void Module::semantic2()
{
for (size_t i = 0; i < deferred.dim; i++)
{
Dsymbol *sd = deferred.tdata()[i];
Dsymbol *sd = deferred[i];
sd->error("unable to resolve forward reference in definition");
}
@@ -892,7 +891,7 @@ void Module::semantic2()
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = members->tdata()[i];
s = (*members)[i];
s->semantic2(sc);
}
@@ -920,7 +919,7 @@ void Module::semantic3()
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = members->tdata()[i];
s = (*members)[i];
//printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
s->semantic3(sc);
}
@@ -943,7 +942,7 @@ void Module::inlineScan()
//printf("Module = %p\n", sc.scopesym);
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
//if (global.params.verbose)
//printf("inline scan symbol %s\n", s->toChars());
@@ -968,7 +967,7 @@ void Module::gensymfile()
buf.writenl();
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
s->toCBuffer(&buf, &hgs);
}
@@ -1029,7 +1028,7 @@ Dsymbol *Module::symtabInsert(Dsymbol *s)
void Module::clearCache()
{
for (size_t i = 0; i < amodules.dim; i++)
{ Module *m = amodules.tdata()[i];
{ Module *m = amodules[i];
m->searchCacheIdent = NULL;
}
}
@@ -1043,7 +1042,7 @@ void Module::addDeferredSemantic(Dsymbol *s)
// Don't add it if it is already there
for (size_t i = 0; i < deferred.dim; i++)
{
Dsymbol *sd = deferred.tdata()[i];
Dsymbol *sd = deferred[i];
if (sd == s)
return;
@@ -1121,7 +1120,7 @@ int Module::imports(Module *m)
}
#endif
for (size_t i = 0; i < aimports.dim; i++)
{ Module *mi = aimports.tdata()[i];
{ Module *mi = aimports[i];
if (mi == m)
return TRUE;
if (!mi->insearch)
@@ -1145,7 +1144,7 @@ int Module::selfImports()
if (!selfimports)
{
for (size_t i = 0; i < amodules.dim; i++)
{ Module *mi = amodules.tdata()[i];
{ Module *mi = amodules[i];
//printf("\t[%d] %s\n", i, mi->toChars());
mi->insearch = 0;
}
@@ -1153,7 +1152,7 @@ int Module::selfImports()
selfimports = imports(this) + 1;
for (size_t i = 0; i < amodules.dim; i++)
{ Module *mi = amodules.tdata()[i];
{ Module *mi = amodules[i];
//printf("\t[%d] %s\n", i, mi->toChars());
mi->insearch = 0;
}
@@ -1177,7 +1176,7 @@ char *ModuleDeclaration::toChars()
if (packages && packages->dim)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = packages->tdata()[i];
{ Identifier *pid = (*packages)[i];
buf.writestring(pid->toChars());
buf.writeByte('.');
@@ -1214,7 +1213,7 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
if (packages)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = packages->tdata()[i];
{ Identifier *pid = (*packages)[i];
Dsymbol *p;
p = dst->lookup(pid);

View File

@@ -137,10 +137,8 @@ struct Module : Package
bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
#if IN_LLVM
void parse(bool gen_docs = false); // syntactic parse
#elif IN_GCC
void setDocfile(); // set docfile member
void parse(bool dump_source = false); // syntactic parse
#else
void setDocfile(); // set docfile member
void parse(); // syntactic parse
#endif
void importAll(Scope *sc);

View File

@@ -494,7 +494,7 @@ Type *Type::merge()
else
{
sv2->ptrvalue = this;
deco = (char *)sv2->lstring.string;
deco = (char *)sv2->toDchars();
}
//printf("new value, deco = '%s' %p\n", t->deco, t->deco);
}
@@ -776,7 +776,7 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
e = v->type->defaultInit(loc);
}
}
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
// if (!e->isConst())
// error(loc, ".init cannot be evaluated at compile time");
}
@@ -804,7 +804,7 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
return getProperty(e->loc, ident);
}
unsigned Type::memalign(unsigned salign)
structalign_t Type::memalign(structalign_t salign)
{
return salign;
}
@@ -1923,7 +1923,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
sc = sc->push(sym);
dim = dim->semantic(sc);
dim = dim->optimize(WANTvalue | WANTinterpret);
dim = dim->ctfeInterpret();
uinteger_t d = dim->toUInteger();
sc = sc->pop();
@@ -1985,7 +1985,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
{ TupleDeclaration *sd = s->isTupleDeclaration();
dim = semanticLength(sc, sd, dim);
dim = dim->optimize(WANTvalue | WANTinterpret);
dim = dim->ctfeInterpret();
uinteger_t d = dim->toUInteger();
if (d >= sd->objects->dim)
@@ -2012,7 +2012,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
if (errors != global.errors)
goto Lerror;
dim = dim->optimize(WANTvalue | WANTinterpret);
dim = dim->ctfeInterpret();
if (sc && sc->parameterSpecialization && dim->op == TOKvar &&
((VarExp *)dim)->var->storage_class & STCtemplateparameter)
{
@@ -2132,7 +2132,7 @@ int TypeSArray::isString()
return nty == Tchar || nty == Twchar || nty == Tdchar;
}
unsigned TypeSArray::memalign(unsigned salign)
structalign_t TypeSArray::memalign(structalign_t salign)
{
return next->memalign(salign);
}
@@ -3036,8 +3036,6 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd
return;
}
inuse++;
if (next && (!ident || ident->toHChars2() == ident->toChars()))
next->toCBuffer2(buf, hgs, 0);
if (hgs->ddoc != 1)
{
switch (linkage)
@@ -3054,10 +3052,17 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd
default:
assert(0);
}
if (!hgs->hdrgen && p)
{
buf->writestring("extern (");
buf->writestring(p);
buf->writestring(") ");
}
}
if (next && (!ident || ident->toHChars2() == ident->toChars()))
{ next->toCBuffer2(buf, hgs, 0);
}
if (!hgs->hdrgen && p)
buf->writestring(p);
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toHChars2());
@@ -3077,39 +3082,52 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd
inuse--;
}
// kind is inserted before the argument list and will usually be "function" or "delegate".
void functionToCBuffer2(TypeFunction *t, OutBuffer *buf, HdrGenState *hgs, int mod, const char *kind)
{
if (hgs->ddoc != 1)
{
const char *p = NULL;
switch (t->linkage)
{
case LINKd: p = NULL; break;
case LINKc: p = "C"; break;
case LINKwindows: p = "Windows"; break;
case LINKpascal: p = "Pascal"; break;
case LINKcpp: p = "C++"; break;
#if IN_LLVM
case LINKintrinsic: p = "Intrinsic"; break;
#endif
default:
assert(0);
}
if (!hgs->hdrgen && p)
{
buf->writestring("extern (");
buf->writestring(p);
buf->writestring(") ");
}
}
if (t->next)
{
t->next->toCBuffer2(buf, hgs, 0);
buf->writeByte(' ');
}
buf->writestring(kind);
Parameter::argsToCBuffer(buf, hgs, t->parameters, t->varargs);
}
void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
const char *p = NULL;
//printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref);
if (inuse)
{ inuse = 2; // flag error to caller
return;
}
inuse++;
if (next)
next->toCBuffer2(buf, hgs, 0);
if (hgs->ddoc != 1)
{
switch (linkage)
{
case LINKd: p = NULL; break;
case LINKc: p = " C"; break;
case LINKwindows: p = " Windows"; break;
case LINKpascal: p = " Pascal"; break;
case LINKcpp: p = " C++"; break;
// LDC
case LINKintrinsic: p = "Intrinsic"; break;
functionToCBuffer2(this, buf, hgs, mod, "function");
default:
assert(0);
}
}
if (!hgs->hdrgen && p)
buf->writestring(p);
buf->writestring(" function");
Parameter::argsToCBuffer(buf, hgs, parameters, varargs);
inuse--;
}
@@ -3464,11 +3482,8 @@ void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ toCBuffer3(buf, hgs, mod);
return;
}
TypeFunction *tf = (TypeFunction *)next;
tf->next->toCBuffer2(buf, hgs, 0);
buf->writestring(" delegate");
Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
functionToCBuffer2((TypeFunction *)next, buf, hgs, mod, "delegate");
}
Expression *TypeDelegate::defaultInit(Loc loc)
@@ -3496,14 +3511,33 @@ Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident)
#endif
if (ident == Id::ptr)
{
#if IN_LLVM
e = new GEPExp(e->loc, e, ident, 0);
#endif
e->type = tvoidptr;
return e;
}
else if (ident == Id::funcptr)
{
if (!e->isLvalue())
{
Identifier *idtmp = Lexer::uniqueId("__dgtmp");
VarDeclaration *tmp = new VarDeclaration(e->loc, this, idtmp, new ExpInitializer(0, e));
tmp->storage_class |= STCctfe;
e = new DeclarationExp(e->loc, tmp);
e = new CommaExp(e->loc, e, new VarExp(e->loc, tmp));
e = e->semantic(sc);
}
#if IN_LLVM
e = new GEPExp(e->loc, e, ident, 1);
#else
e = e->addressOf(sc);
e->type = tvoidptr;
e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE));
e->type = tvoidptr;
e = new PtrExp(e->loc, e);
#endif
e->type = next->pointerTo();
return e;
}
else
@@ -3534,7 +3568,7 @@ void TypeQualified::syntaxCopyHelper(TypeQualified *t)
idents.setDim(t->idents.dim);
for (size_t i = 0; i < idents.dim; i++)
{
Identifier *id = (Identifier *)t->idents.data[i];
Identifier *id = t->idents[i];
if (id->dyncast() == DYNCAST_DSYMBOL)
{
TemplateInstance *ti = (TemplateInstance *)id;
@@ -3542,7 +3576,7 @@ void TypeQualified::syntaxCopyHelper(TypeQualified *t)
ti = (TemplateInstance *)ti->syntaxCopy(NULL);
id = (Identifier *)ti;
}
idents.data[i] = id;
idents[i] = id;
}
}
@@ -3555,7 +3589,7 @@ void TypeQualified::addIdent(Identifier *ident)
void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
{
for (size_t i = 0; i < idents.dim; i++)
{ Identifier *id = (Identifier *)idents.data[i];
{ Identifier *id = idents[i];
buf->writeByte('.');
@@ -4741,7 +4775,12 @@ unsigned TypeStruct::alignsize()
sym->size(0); // give error for forward references
sz = sym->alignsize;
if (sz > sym->structalign)
if (sym->structalign == STRUCTALIGN_DEFAULT)
{
if (sz > 8)
sz = 8;
}
else if (sz > sym->structalign)
sz = sym->structalign;
return sz;
}
@@ -4965,7 +5004,7 @@ L1:
return de->semantic(sc);
}
unsigned TypeStruct::memalign(unsigned salign)
structalign_t TypeStruct::memalign(structalign_t salign)
{
sym->size(0); // give error for forward references
return sym->structalign;
@@ -5692,11 +5731,11 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc)
TypeTuple *tt = (TypeTuple *)tbn;
lwr = semanticLength(sc, tbn, lwr);
lwr = lwr->optimize(WANTvalue | WANTinterpret);
lwr = lwr->ctfeInterpret();
uinteger_t i1 = lwr->toUInteger();
upr = semanticLength(sc, tbn, upr);
upr = upr->optimize(WANTvalue | WANTinterpret);
upr = upr->ctfeInterpret();
uinteger_t i2 = upr->toUInteger();
if (!(i1 <= i2 && i2 <= tt->arguments->dim))
@@ -5736,11 +5775,11 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
sc = sc->push(sym);
lwr = lwr->semantic(sc);
lwr = lwr->optimize(WANTvalue | WANTinterpret);
lwr = lwr->ctfeInterpret();
uinteger_t i1 = lwr->toUInteger();
upr = upr->semantic(sc);
upr = upr->optimize(WANTvalue | WANTinterpret);
upr = upr->ctfeInterpret();
uinteger_t i2 = upr->toUInteger();
sc = sc->pop();
@@ -5831,27 +5870,8 @@ char *Parameter::argsTypesToChars(Parameters *args, int varargs)
{
OutBuffer *buf = new OutBuffer();
buf->writeByte('(');
if (args)
{ OutBuffer argbuf;
HdrGenState hgs;
for (size_t i = 0; i < args->dim; i++)
{ if (i)
buf->writeByte(',');
Parameter *arg = args->tdata()[i];
argbuf.reset();
arg->type->toCBuffer2(&argbuf, &hgs, 0);
buf->write(&argbuf);
}
if (varargs)
{
if (args->dim && varargs == 1)
buf->writeByte(',');
buf->writestring("...");
}
}
buf->writeByte(')');
HdrGenState hgs;
argsToCBuffer(buf, &hgs, args, varargs);
return buf->toChars();
}

View File

@@ -252,7 +252,7 @@ struct Type : Object
virtual ClassDeclaration *isClassHandle();
virtual Expression *getProperty(Loc loc, Identifier *ident);
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
virtual unsigned memalign(unsigned salign);
virtual structalign_t memalign(structalign_t salign);
virtual Expression *defaultInit(Loc loc = 0);
virtual Expression *defaultInitLiteral(Loc loc);
virtual Expression *voidInitLiteral(VarDeclaration *var);
@@ -305,6 +305,7 @@ struct TypeError : Type
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
TypeTuple *toArgTypes();
};
#if DMDV2
@@ -388,7 +389,7 @@ struct TypeSArray : TypeArray
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit(Loc loc);
unsigned memalign(unsigned salign);
structalign_t memalign(structalign_t salign);
MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
@@ -644,7 +645,7 @@ struct TypeStruct : Type
void toDecoBuffer(OutBuffer *buf, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
unsigned memalign(unsigned salign);
structalign_t memalign(structalign_t salign);
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h> // memset()
#if _MSC_VER
#include <complex>
#else

View File

@@ -12,6 +12,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h> // strlen(),memcpy()
#include "rmem.h"
#include "lexer.h"
@@ -78,25 +79,6 @@ Dsymbols *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;
@@ -397,7 +379,11 @@ Dsymbols *Parser::parseDeclDefs(int once)
{
nextToken();
if (token.value == TOKint32v && token.uns64value > 0)
{
if (token.uns64value & (token.uns64value - 1))
error("align(%s) must be a power of 2", token.toChars());
n = (unsigned)token.uns64value;
}
else
{ error("positive integer expected, not %s", token.toChars());
n = 1;
@@ -420,7 +406,7 @@ Dsymbols *Parser::parseDeclDefs(int once)
nextToken();
check(TOKlparen);
if (token.value != TOKidentifier)
{ error("pragma(identifier expected");
{ error("pragma(identifier) expected");
goto Lerror;
}
ident = token.ident;
@@ -2746,7 +2732,15 @@ Initializer *Parser::parseInitializer()
if (comma == 1)
error("comma expected separating array initializers, not %s", token.toChars());
value = parseInitializer();
ia->addInit(NULL, value);
if (token.value == TOKcolon)
{
nextToken();
e = value->toExpression();
value = parseInitializer();
}
else
e = NULL;
ia->addInit(e, value);
comma = 1;
continue;
@@ -3520,7 +3514,7 @@ Statement *Parser::parseStatement(int flags)
Loc loc = this->loc;
nextToken();
if (token.value == TOKlcurly)
if (token.value == TOKlcurly || token.value != TOKlparen)
{
t = NULL;
id = NULL;

View File

@@ -40,7 +40,6 @@
#include "port.h"
#include "root.h"
#include "dchar.h"
#include "rmem.h"

View File

@@ -1,482 +0,0 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "dchar.h"
#include "rmem.h"
#if M_UNICODE
// Converts a char string to Unicode
dchar *Dchar::dup(char *p)
{
dchar *s;
size_t len;
if (!p)
return NULL;
len = strlen(p);
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
for (unsigned i = 0; i < len; i++)
{
s[i] = (dchar)(p[i] & 0xFF);
}
s[len] = 0;
return s;
}
dchar *Dchar::memchr(dchar *p, int c, int count)
{
int u;
for (u = 0; u < count; u++)
{
if (p[u] == c)
return p + u;
}
return NULL;
}
#if _WIN32 && __DMC__
__declspec(naked)
unsigned Dchar::calcHash(const dchar *str, unsigned len)
{
__asm
{
mov ECX,4[ESP]
mov EDX,8[ESP]
xor EAX,EAX
test EDX,EDX
je L92
LC8: cmp EDX,1
je L98
cmp EDX,2
je LAE
add EAX,[ECX]
// imul EAX,EAX,025h
lea EAX,[EAX][EAX*8]
add ECX,4
sub EDX,2
jmp LC8
L98: mov DX,[ECX]
and EDX,0FFFFh
add EAX,EDX
ret
LAE: add EAX,[ECX]
L92: ret
}
}
#else
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
unsigned hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str;
return hash;
case 2:
hash += *(const uint32_t *)str;
return hash;
default:
hash += *(const uint32_t *)str;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#endif
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str | 0x20;
return hash;
case 2:
hash += *(const uint32_t *)str | 0x200020;
return hash;
default:
hash += *(const uint32_t *)str | 0x200020;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#elif MCBS
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str;
return hash;
case 3:
hash *= 37;
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str;
str += 4;
len -= 4;
break;
}
}
}
#elif UTF8
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
char Dchar::mblen[256] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
};
dchar *Dchar::dec(dchar *pstart, dchar *p)
{
while ((p[-1] & 0xC0) == 0x80)
p--;
return p;
}
int Dchar::get(dchar *p)
{
unsigned c;
unsigned char *q = (unsigned char *)p;
c = q[0];
switch (mblen[c])
{
case 2:
c = ((c - 0xC0) << 6) |
(q[1] - 0x80);
break;
case 3:
c = ((c - 0xE0) << 12) |
((q[1] - 0x80) << 6) |
(q[2] - 0x80);
break;
case 4:
c = ((c - 0xF0) << 18) |
((q[1] - 0x80) << 12) |
((q[2] - 0x80) << 6) |
(q[3] - 0x80);
break;
case 5:
c = ((c - 0xF8) << 24) |
((q[1] - 0x80) << 18) |
((q[2] - 0x80) << 12) |
((q[3] - 0x80) << 6) |
(q[4] - 0x80);
break;
case 6:
c = ((c - 0xFC) << 30) |
((q[1] - 0x80) << 24) |
((q[2] - 0x80) << 18) |
((q[3] - 0x80) << 12) |
((q[4] - 0x80) << 6) |
(q[5] - 0x80);
break;
}
return c;
}
dchar *Dchar::put(dchar *p, unsigned c)
{
if (c <= 0x7F)
{
*p++ = c;
}
else if (c <= 0x7FF)
{
p[0] = 0xC0 + (c >> 6);
p[1] = 0x80 + (c & 0x3F);
p += 2;
}
else if (c <= 0xFFFF)
{
p[0] = 0xE0 + (c >> 12);
p[1] = 0x80 + ((c >> 6) & 0x3F);
p[2] = 0x80 + (c & 0x3F);
p += 3;
}
else if (c <= 0x1FFFFF)
{
p[0] = 0xF0 + (c >> 18);
p[1] = 0x80 + ((c >> 12) & 0x3F);
p[2] = 0x80 + ((c >> 6) & 0x3F);
p[3] = 0x80 + (c & 0x3F);
p += 4;
}
else if (c <= 0x3FFFFFF)
{
p[0] = 0xF8 + (c >> 24);
p[1] = 0x80 + ((c >> 18) & 0x3F);
p[2] = 0x80 + ((c >> 12) & 0x3F);
p[3] = 0x80 + ((c >> 6) & 0x3F);
p[4] = 0x80 + (c & 0x3F);
p += 5;
}
else if (c <= 0x7FFFFFFF)
{
p[0] = 0xFC + (c >> 30);
p[1] = 0x80 + ((c >> 24) & 0x3F);
p[2] = 0x80 + ((c >> 18) & 0x3F);
p[3] = 0x80 + ((c >> 12) & 0x3F);
p[4] = 0x80 + ((c >> 6) & 0x3F);
p[5] = 0x80 + (c & 0x3F);
p += 6;
}
else
assert(0); // not a UCS-4 character
return p;
}
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
#else // ascii
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str | 0x20;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str | 0x2020;
return hash;
case 3:
hash *= 37;
hash += ((*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]) | 0x202020;
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str | 0x20202020;
str += 4;
len -= 4;
break;
}
}
}
#endif
#if 0
#include <stdio.h>
void main()
{
// Print out values to hardcode into Dchar::mblen[]
int c;
int s;
for (c = 0; c < 256; c++)
{
s = 1;
if (c >= 0xC0 && c <= 0xDF)
s = 2;
if (c >= 0xE0 && c <= 0xEF)
s = 3;
if (c >= 0xF0 && c <= 0xF7)
s = 4;
if (c >= 0xF8 && c <= 0xFB)
s = 5;
if (c >= 0xFC && c <= 0xFD)
s = 6;
printf("%d", s);
if ((c & 15) == 15)
printf(",\n");
else
printf(",");
}
}
#endif

View File

@@ -1,194 +0,0 @@
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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 DCHAR_H
#define DCHAR_H
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#endif
//#include "root.h"
typedef size_t hash_t;
#undef TEXT
// NOTE: All functions accepting pointer arguments must not be NULL
#if M_UNICODE
#include <string.h>
#include <wchar.h>
typedef wchar_t dchar;
#define TEXT(x) L##x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return wcslen(p); }
static dchar get(dchar *p) { return *p; }
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2)
{
#if __DMC__
if (!*s1 && !*s2) // wcscmp is broken
return 0;
#endif
return wcscmp(s1, s2);
#if 0
return (*s1 == *s2)
? wcscmp(s1, s2)
: ((int)*s1 - (int)*s2);
#endif
}
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return iswalpha(c); }
static int isUpper(dchar c) { return iswupper(c); }
static int isLower(dchar c) { return iswlower(c); }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
static dchar *dup(char *p);
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
static dchar *memchr(dchar *p, int c, int count);
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#elif MCBS
#include <limits.h>
#include <mbstring.h>
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax MB_LEN_MAX
#elif UTF8
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 6
struct Dchar
{
static char mblen[256];
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
static dchar *dec(dchar *pstart, dchar *p);
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p);
static int getprev(dchar *pstart, dchar *p)
{ return *dec(pstart, p) & 0xFF; }
static dchar *put(dchar *p, unsigned c);
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
};
#else
#include <string.h>
#ifndef GCC_SAFE_DMD
#include <ctype.h>
#endif
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p) { return *p & 0xFF; }
static int getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1] & 0xFF; }
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
#ifndef GCC_SAFE_DMD
static int isAlpha(dchar c) { return isalpha((unsigned char)c); }
static int isUpper(dchar c) { return isupper((unsigned char)c); }
static int isLower(dchar c) { return islower((unsigned char)c); }
static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); }
static int isLocaleLower(dchar c) { return islower((unsigned char)c); }
static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
#endif
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
#ifdef __GNUC__
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
#else
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
#endif
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#endif
#endif

View File

@@ -1,63 +0,0 @@
// lstring.c
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#include <stdlib.h>
#include "dchar.h"
#include "rmem.h"
#include "lstring.h"
#ifdef _MSC_VER // prevent compiler internal crash
Lstring Lstring::zero;
#else
Lstring Lstring::zero = LSTRING_EMPTY();
#endif
Lstring *Lstring::ctor(const dchar *p, unsigned length)
{
Lstring *s;
s = alloc(length);
memcpy(s->string, p, length * sizeof(dchar));
return s;
}
Lstring *Lstring::alloc(unsigned length)
{
Lstring *s;
s = (Lstring *)mem.malloc(size(length));
s->length = length;
s->string[length] = 0;
return s;
}
Lstring *Lstring::append(const Lstring *s)
{
Lstring *t;
if (!s->length)
return this;
t = alloc(length + s->length);
memcpy(t->string, string, length * sizeof(dchar));
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
return t;
}
Lstring *Lstring::substring(int start, int end)
{
Lstring *t;
if (start == end)
return &zero;
t = alloc(end - start);
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
return t;
}

View File

@@ -1,74 +0,0 @@
// lstring.h
// length-prefixed strings
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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 LSTRING_H
#define LSTRING_H 1
#include "dchar.h"
struct Lstring
{
unsigned length;
#ifndef IN_GCC
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
#endif
dchar string[];
static Lstring zero; // 0 length string
// No constructors because we want to be able to statically
// initialize Lstring's, and Lstrings are of variable size.
#if M_UNICODE
#define LSTRING(p,length) { length, L##p }
#else
#define LSTRING(p,length) { length, p }
#endif
#if __GNUC__
#define LSTRING_EMPTY() { 0 }
#else
#define LSTRING_EMPTY() LSTRING("", 0)
#endif
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
static Lstring *ctor(const dchar *p, unsigned length);
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
static Lstring *alloc(unsigned length);
Lstring *clone();
unsigned len() { return length; }
dchar *toDchars() { return string; }
hash_t hash() { return Dchar::calcHash(string, length); }
hash_t ihash() { return Dchar::icalcHash(string, length); }
static int cmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
}
static int icmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
}
Lstring *append(const Lstring *s);
Lstring *substring(int start, int end);
};
#endif

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -18,6 +18,7 @@
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include <ctype.h>
#if (defined (__SVR4) && defined (__sun))
#include <alloca.h>
@@ -49,7 +50,6 @@
#include "port.h"
#include "root.h"
#include "dchar.h"
#include "rmem.h"
#include "mars.h"
@@ -143,22 +143,6 @@ void error(const char *format, ...)
exit(EXIT_FAILURE);
}
#if M_UNICODE
void error(const dchar *format, ...)
{
va_list ap;
va_start(ap, format);
printf("Error: ");
vwprintf(format, ap);
va_end( ap );
printf("\n");
fflush(stdout);
exit(EXIT_FAILURE);
}
#endif
void error_mem()
{
error("out of memory");
@@ -207,15 +191,6 @@ char *Object::toChars()
return (char *)"Object";
}
dchar *Object::toDchars()
{
#if M_UNICODE
return L"Object";
#else
return toChars();
#endif
}
int Object::dyncast()
{
return 0;
@@ -1620,30 +1595,6 @@ void OutBuffer::writestring(const char *string)
write(string,strlen(string));
}
void OutBuffer::writedstring(const char *string)
{
#if M_UNICODE
for (; *string; string++)
{
writedchar(*string);
}
#else
write(string,strlen(string));
#endif
}
void OutBuffer::writedstring(const wchar_t *string)
{
#if M_UNICODE
write(string,wcslen(string) * sizeof(wchar_t));
#else
for (; *string; string++)
{
writedchar(*string);
}
#endif
}
void OutBuffer::prependstring(const char *string)
{ unsigned len;
@@ -1657,18 +1608,10 @@ void OutBuffer::prependstring(const char *string)
void OutBuffer::writenl()
{
#if _WIN32
#if M_UNICODE
write4(0x000A000D); // newline is CR,LF on Microsoft OS's
#else
writeword(0x0A0D); // newline is CR,LF on Microsoft OS's
#endif
#else
#if M_UNICODE
writeword('\n');
#else
writeByte('\n');
#endif
#endif
}
void OutBuffer::writeByte(unsigned b)
@@ -1730,13 +1673,6 @@ void OutBuffer::writeUTF8(unsigned b)
assert(0);
}
void OutBuffer::writedchar(unsigned b)
{
reserve(Dchar_mbmax * sizeof(dchar));
offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) -
this->data;
}
void OutBuffer::prependbyte(unsigned b)
{
reserve(1);
@@ -1884,46 +1820,6 @@ void OutBuffer::vprintf(const char *format, va_list args)
write(p,count);
}
#if M_UNICODE
void OutBuffer::vprintf(const wchar_t *format, va_list args)
{
dchar buffer[128];
dchar *p;
unsigned psize;
int count;
WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format);
p = buffer;
psize = sizeof(buffer) / sizeof(buffer[0]);
for (;;)
{
#if _WIN32
count = _vsnwprintf(p,psize,format,args);
if (count != -1)
break;
psize *= 2;
#elif POSIX
va_list va;
va_copy(va, args);
count = vsnwprintf(p,psize,format,va);
va_end(va);
if (count == -1)
psize *= 2;
else if (count >= psize)
psize = count + 1;
else
break;
#else
assert(0);
#endif
p = (dchar *) alloca(psize * 2); // buffer too small, try again with larger size
}
write(p,count * 2);
}
#endif
void OutBuffer::printf(const char *format, ...)
{
va_list ap;
@@ -1932,16 +1828,6 @@ void OutBuffer::printf(const char *format, ...)
va_end(ap);
}
#if M_UNICODE
void OutBuffer::printf(const wchar_t *format, ...)
{
va_list ap;
va_start(ap, format);
vprintf(format,ap);
va_end(ap);
}
#endif
void OutBuffer::bracket(char left, char right)
{
reserve(2);

View File

@@ -1,5 +1,4 @@
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
@@ -32,7 +31,6 @@
typedef size_t hash_t;
#include "longdouble.h"
#include "dchar.h"
char *wchar2ascii(wchar_t *);
int wcharIsAscii(wchar_t *);
@@ -105,7 +103,6 @@ struct Object
virtual void print();
virtual char *toChars();
virtual dchar *toDchars();
virtual void toBuffer(OutBuffer *buf);
/**
@@ -295,14 +292,11 @@ struct OutBuffer : Object
void write(const void *data, unsigned nbytes);
void writebstring(unsigned char *string);
void writestring(const char *string);
void writedstring(const char *string);
void writedstring(const wchar_t *string);
void prependstring(const char *string);
void writenl(); // write newline
void writeByte(unsigned b);
void writebyte(unsigned b) { writeByte(b); }
void writeUTF8(unsigned b);
void writedchar(unsigned b);
void prependbyte(unsigned b);
void writeword(unsigned w);
void writeUTF16(unsigned w);

View File

@@ -9,15 +9,70 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h> // uint{8|16|32}_t
#include <string.h> // memcpy()
#include <stdlib.h>
#include "root.h"
#include "rmem.h"
#include "dchar.h"
#include "lstring.h"
#include "rmem.h" // mem
#include "stringtable.h"
hash_t calcHash(const char *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
void StringValue::ctor(const char *p, unsigned length)
{
this->length = length;
this->lstring[length] = 0;
memcpy(this->lstring, p, length * sizeof(char));
}
void StringTable::init(unsigned size)
{
table = (void **)mem.calloc(size, sizeof(void *));
@@ -46,21 +101,20 @@ struct StringEntry
StringValue value;
static StringEntry *alloc(const dchar *s, unsigned len);
static StringEntry *alloc(const char *s, unsigned len);
};
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
StringEntry *StringEntry::alloc(const char *s, unsigned len)
{
StringEntry *se;
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
se->value.lstring.length = len;
se->hash = Dchar::calcHash(s,len);
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) + len + 1);
se->value.ctor(s, len);
se->hash = calcHash(s,len);
return se;
}
void **StringTable::search(const dchar *s, unsigned len)
void **StringTable::search(const char *s, unsigned len)
{
hash_t hash;
unsigned u;
@@ -68,7 +122,7 @@ void **StringTable::search(const dchar *s, unsigned len)
StringEntry **se;
//printf("StringTable::search(%p,%d)\n",s,len);
hash = Dchar::calcHash(s,len);
hash = calcHash(s,len);
u = hash % tabledim;
se = (StringEntry **)&table[u];
//printf("\thash = %d, u = %d\n",hash,u);
@@ -77,10 +131,10 @@ void **StringTable::search(const dchar *s, unsigned len)
cmp = (*se)->hash - hash;
if (cmp == 0)
{
cmp = (*se)->value.lstring.len() - len;
cmp = (*se)->value.len() - len;
if (cmp == 0)
{
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
cmp = ::memcmp(s,(*se)->value.toDchars(),len);
if (cmp == 0)
break;
}
@@ -94,7 +148,7 @@ void **StringTable::search(const dchar *s, unsigned len)
return (void **)se;
}
StringValue *StringTable::lookup(const dchar *s, unsigned len)
StringValue *StringTable::lookup(const char *s, unsigned len)
{ StringEntry *se;
se = *(StringEntry **)search(s,len);
@@ -104,7 +158,7 @@ StringValue *StringTable::lookup(const dchar *s, unsigned len)
return NULL;
}
StringValue *StringTable::update(const dchar *s, unsigned len)
StringValue *StringTable::update(const char *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
@@ -118,7 +172,7 @@ StringValue *StringTable::update(const dchar *s, unsigned len)
return &se->value;
}
StringValue *StringTable::insert(const dchar *s, unsigned len)
StringValue *StringTable::insert(const char *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
@@ -133,7 +187,3 @@ StringValue *StringTable::insert(const dchar *s, unsigned len)
}
return &se->value;
}

View File

@@ -1,3 +1,4 @@
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
@@ -15,34 +16,56 @@
#endif
#include "root.h"
#include "dchar.h"
#include "lstring.h"
struct StringEntry;
// StringValue is a variable-length structure as indicated by the last array
// member with unspecified size. It has neither proper c'tors nor a factory
// method because the only thing which should be creating these is StringTable.
struct StringValue
{
union
{ int intvalue;
{
void *ptrvalue;
dchar *string;
char *string;
};
Lstring lstring;
private:
unsigned length;
#ifndef IN_GCC
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
#endif
char lstring[];
public:
unsigned len() const { return length; }
const char *toDchars() const { return lstring; }
private:
friend struct StringEntry;
StringValue(); // not constructible
// This is more like a placement new c'tor
void ctor(const char *p, unsigned length);
};
struct StringTable
{
private:
void **table;
unsigned count;
unsigned tabledim;
public:
void init(unsigned size = 37);
~StringTable();
StringValue *lookup(const dchar *s, unsigned len);
StringValue *insert(const dchar *s, unsigned len);
StringValue *update(const dchar *s, unsigned len);
StringValue *lookup(const char *s, unsigned len);
StringValue *insert(const char *s, unsigned len);
StringValue *update(const char *s, unsigned len);
private:
void **search(const dchar *s, unsigned len);
void **search(const char *s, unsigned len);
};
#endif

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h> // strlen()
#include "root.h"
#include "speller.h"

View File

@@ -86,7 +86,7 @@ struct Scope
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
unsigned structalign; // alignment for struct members
structalign_t structalign; // alignment for struct members
enum LINK linkage; // linkage for external functions
enum PROT protection; // protection for class members

View File

@@ -388,7 +388,7 @@ Statements *CompileStatement::flatten(Scope *sc)
//printf("CompileStatement::flatten() %s\n", exp->toChars());
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
exp = exp->optimize(WANTvalue | WANTinterpret);
exp = exp->ctfeInterpret();
if (exp->op == TOKerror)
return NULL;
StringExp *se = exp->toString();
@@ -1739,18 +1739,6 @@ Statement *ForeachStatement::semantic(Scope *sc)
Type *tret = func->type->nextOf();
// Need a variable to hold value from any return statements in body.
if (!sc->func->vresult && tret && tret != Type::tvoid)
{
VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
v->noscope = 1;
v->semantic(sc);
if (!sc->insert(v))
assert(0);
v->parent = sc->func;
sc->func->vresult = v;
}
/* Turn body into the function literal:
* int delegate(ref T arg) { body }
*/
@@ -2558,7 +2546,8 @@ Statement *PragmaStatement::semantic(Scope *sc)
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->op != TOKerror && e->op != TOKtype)
e = e->ctfeInterpret();
StringExp *se = e->toString();
if (se)
{
@@ -2584,7 +2573,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
(*args)[0] = e;
StringExp *se = e->toString();
if (!se)
@@ -2615,7 +2604,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
(*args)[0] = e;
Dsymbol *sa = getDsymbol(e);
if (!sa || !sa->isFuncDeclaration())
@@ -2954,7 +2943,7 @@ Statement *CaseStatement::semantic(Scope *sc)
}
exp = exp->implicitCastTo(sc, sw->condition->type);
exp = exp->optimize(WANTvalue | WANTinterpret);
exp = exp->ctfeInterpret();
if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror)
{
error("case must be a string or an integral constant, not %s", exp->toChars());
@@ -3054,11 +3043,11 @@ Statement *CaseRangeStatement::semantic(Scope *sc)
first = first->semantic(sc);
first = first->implicitCastTo(sc, sw->condition->type);
first = first->optimize(WANTvalue | WANTinterpret);
first = first->ctfeInterpret();
last = last->semantic(sc);
last = last->implicitCastTo(sc, sw->condition->type);
last = last->optimize(WANTvalue | WANTinterpret);
last = last->ctfeInterpret();
if (first->op == TOKerror || last->op == TOKerror)
return statement ? statement->semantic(sc) : NULL;
@@ -3286,6 +3275,7 @@ ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
: Statement(loc)
{
this->exp = exp;
this->implicit0 = 0;
}
Statement *ReturnStatement::syntaxCopy()
@@ -3303,7 +3293,6 @@ Statement *ReturnStatement::semantic(Scope *sc)
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
Scope *scx = sc;
int implicit0 = 0;
Expression *eorg = NULL;
if (fd->fes)
@@ -3370,6 +3359,12 @@ Statement *ReturnStatement::semantic(Scope *sc)
else
fd->nrvo_can = 0;
#if 0
if (fd->returnLabel && tbret && tbret->ty != Tvoid)
{
}
else
#endif
if (fd->inferRetType)
{
Type *tfret = fd->type->nextOf();
@@ -3455,10 +3450,11 @@ Statement *ReturnStatement::semantic(Scope *sc)
// Construct: return vresult;
if (!fd->vresult)
{ // Declare vresult
Scope *sco = fd->scout ? fd->scout : scx;
VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
v->noscope = 1;
v->semantic(scx);
if (!scx->insert(v))
v->semantic(sco);
if (!sco->insert(v))
assert(0);
v->parent = fd;
fd->vresult = v;
@@ -3481,7 +3477,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
{
if (fd->returnLabel && tbret->ty != Tvoid)
{
assert(fd->vresult);
fd->buildResultVar();
VarExp *v = new VarExp(0, fd->vresult);
assert(eorg);
@@ -3798,9 +3794,16 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
{ /* Cast the interface to an object, as the object has the monitor,
* not the interface.
*/
Type *t = new TypeIdentifier(0, Id::Object);
if (!ClassDeclaration::object)
{
error("missing or corrupt object.d");
fatal();
}
Type *t = ClassDeclaration::object->type;
t = t->semantic(0, sc)->toBasetype();
assert(t->ty == Tclass);
t = t->semantic(0, sc);
exp = new CastExp(loc, exp, t);
exp = exp->semantic(sc);
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -634,6 +634,7 @@ struct SwitchErrorStatement : Statement
struct ReturnStatement : Statement
{
Expression *exp;
int implicit0;
ReturnStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -54,10 +54,14 @@ void StaticAssert::semantic2(Scope *sc)
{
//printf("StaticAssert::semantic2() %s\n", toChars());
Expression *e = exp->semantic(sc);
if (e->type == Type::terror)
if (!e->type->checkBoolean())
{
if (e->type->toBasetype() != Type::terror)
exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
return;
}
unsigned olderrs = global.errors;
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
if (global.errors != olderrs)
{
errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
@@ -69,7 +73,7 @@ void StaticAssert::semantic2(Scope *sc)
OutBuffer buf;
msg = msg->semantic(sc);
msg = msg->optimize(WANTvalue | WANTinterpret);
msg = msg->ctfeInterpret();
hgs.console = 1;
msg->toCBuffer(&buf, &hgs);
error("%s", buf.toChars());

View File

@@ -97,7 +97,7 @@ void AggregateDeclaration::semantic3(Scope *sc)
sc = sc->push(this);
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
s->semantic3(sc);
}
sc->pop();
@@ -111,7 +111,7 @@ void AggregateDeclaration::inlineScan()
{
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
//printf("inline scan aggregate symbol '%s'\n", s->toChars());
s->inlineScan();
}
@@ -120,7 +120,9 @@ void AggregateDeclaration::inlineScan()
unsigned AggregateDeclaration::size(Loc loc)
{
//printf("AggregateDeclaration::size() = %d\n", structsize);
//printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope);
if (loc.linnum == 0)
loc = this->loc;
if (!members)
error(loc, "unknown size");
if (sizeok != SIZEOKdone && scope)
@@ -153,11 +155,13 @@ int AggregateDeclaration::isExport()
*/
void AggregateDeclaration::alignmember(
unsigned salign, // struct alignment that is in effect
structalign_t salign, // struct alignment that is in effect
unsigned size, // alignment requirement of field
unsigned *poffset)
{
//printf("salign = %d, size = %d, offset = %d\n",salign,size, *poffset);
//printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
if (salign == STRUCTALIGN_DEFAULT)
salign = 8;
if (salign > 1)
{
assert(size != 3);
@@ -178,7 +182,7 @@ unsigned AggregateDeclaration::placeField(
unsigned *nextoffset, // next location in aggregate
unsigned memsize, // size of member
unsigned memalignsize, // size of member for alignment purposes
unsigned memalign, // alignment in effect for this member
structalign_t memalign, // alignment in effect for this member
unsigned *paggsize, // size of aggregate (updated)
unsigned *paggalignsize, // size of aggregate for alignment purposes (updated)
bool isunion // the aggregate is a union
@@ -195,6 +199,8 @@ unsigned AggregateDeclaration::placeField(
if (global.params.is64bit && memalign == 8 && memalignsize == 16)
/* Not sure how to handle this */
;
else if (memalign == STRUCTALIGN_DEFAULT && 8 < memalignsize)
memalignsize = 8;
else if (memalign < memalignsize)
memalignsize = memalign;
if (*paggalignsize < memalignsize)
@@ -212,13 +218,13 @@ int AggregateDeclaration::firstFieldInUnion(int indx)
{
if (isUnionDeclaration())
return 0;
VarDeclaration * vd = fields.tdata()[indx];
VarDeclaration * vd = fields[indx];
int firstNonZero = indx; // first index in the union with non-zero size
for (; ;)
{
if (indx == 0)
return firstNonZero;
VarDeclaration * v = fields.tdata()[indx - 1];
VarDeclaration * v = fields[indx - 1];
if (v->offset != vd->offset)
return firstNonZero;
--indx;
@@ -237,7 +243,7 @@ int AggregateDeclaration::firstFieldInUnion(int indx)
*/
int AggregateDeclaration::numFieldsInUnion(int firstIndex)
{
VarDeclaration * vd = fields.tdata()[firstIndex];
VarDeclaration * vd = fields[firstIndex];
/* If it is a zero-length field, AND we can't find an earlier non-zero
* sized field with the same offset, we assume it's not part of a union.
*/
@@ -247,7 +253,7 @@ int AggregateDeclaration::numFieldsInUnion(int firstIndex)
int count = 1;
for (size_t i = firstIndex+1; i < fields.dim; ++i)
{
VarDeclaration * v = fields.tdata()[i];
VarDeclaration * v = fields[i];
// If offsets are different, they are not in the same union
if (v->offset != vd->offset)
break;
@@ -268,6 +274,8 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
postblit = NULL;
eq = NULL;
#endif
arg1type = NULL;
arg2type = NULL;
// For forward references
type = new TypeStruct(this);
@@ -289,7 +297,7 @@ void StructDeclaration::semantic(Scope *sc)
{
Scope *sc2;
//printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", this, toChars(), sizeok);
//printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);
//static int count; if (++count == 20) halt();
@@ -330,18 +338,12 @@ void StructDeclaration::semantic(Scope *sc)
assert(!isAnonymous());
if (sc->stc & STCabstract)
error("structs, unions cannot be abstract");
#if DMDV2
if (storage_class & STCimmutable)
type = type->invariantOf();
else if (storage_class & STCconst)
type = type->constOf();
#endif
if (sizeok == SIZEOKnone) // if not already done the addMember step
{
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
//printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
s->addMember(sc, this, 1);
}
@@ -379,7 +381,9 @@ void StructDeclaration::semantic(Scope *sc)
// Ungag errors when not speculative
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging() && !isSpeculative())
{
global.gag = 0;
}
s->semantic(sc2);
global.gag = oldgag;
#if 0
@@ -540,6 +544,15 @@ void StructDeclaration::semantic(Scope *sc)
aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
TypeTuple *tup = type->toArgTypes();
size_t dim = tup->arguments->dim;
if (dim >= 1)
{ assert(dim <= 2);
arg1type = (*tup->arguments)[0]->type;
if (dim == 2)
arg2type = (*tup->arguments)[1]->type;
}
if (sc->func)
{
semantic2(sc);
@@ -565,6 +578,7 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
void StructDeclaration::finalizeSize(Scope *sc)
{
//printf("StructDeclaration::finalizeSize() %s\n", toChars());
if (sizeok != SIZEOKnone)
return;
@@ -593,6 +607,23 @@ void StructDeclaration::finalizeSize(Scope *sc)
sizeok = SIZEOKdone;
}
/***************************************
* Return true if struct is POD (Plain Old Data).
* This is defined as:
* not nested
* no postblits, constructors, destructors, or assignment operators
* no fields with with any of those
* The idea being these are compatible with C structs.
*
* Note that D struct constructors can mean POD, since there is always default
* construction with no ctor, but that interferes with OPstrpar which wants it
* on the stack in memory, not in registers.
*/
bool StructDeclaration::isPOD()
{
return true;
}
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->printf("%s ", kind());
@@ -609,7 +640,7 @@ void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);

View File

@@ -86,7 +86,7 @@ int isError(Object *o)
return (t->ty == Terror);
Expression *e = isExpression(o);
if (e)
return (e->op == TOKerror);
return (e->op == TOKerror || !e->type || e->type->ty== Terror);
Tuple *v = isTuple(o);
if (v)
return arrayObjectIsError(&v->objects);
@@ -100,7 +100,7 @@ int arrayObjectIsError(Objects *args)
{
for (size_t i = 0; i < args->dim; i++)
{
Object *o = (Object *)args->data[i];
Object *o = (*args)[i];
if (isError(o))
return 1;
}
@@ -244,8 +244,8 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
goto Lnomatch;
for (size_t i = 0; i < u1->objects.dim; i++)
{
if (!match(u1->objects.tdata()[i],
u2->objects.tdata()[i],
if (!match(u1->objects[i],
u2->objects[i],
tempdecl, sc))
goto Lnomatch;
}
@@ -270,8 +270,8 @@ int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl,
if (oa1->dim != oa2->dim)
return 0;
for (size_t j = 0; j < oa1->dim; j++)
{ Object *o1 = (Object *)oa1->data[j];
Object *o2 = (Object *)oa2->data[j];
{ Object *o1 = (*oa1)[j];
Object *o2 = (*oa2)[j];
if (!match(o1, o2, tempdecl, sc))
{
return 0;
@@ -364,7 +364,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
#if 0
if (parameters)
for (size_t i = 0; i < parameters->dim; i++)
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
{ TemplateParameter *tp = (*parameters)[i];
//printf("\tparameter[%d] = %p\n", i, tp);
TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
@@ -411,8 +411,8 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
p = new TemplateParameters();
p->setDim(parameters->dim);
for (size_t i = 0; i < p->dim; i++)
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
p->data[i] = (void *)tp->syntaxCopy();
{ TemplateParameter *tp = (*parameters)[i];
(*p)[i] = tp->syntaxCopy();
}
}
Expression *e = NULL;
@@ -477,8 +477,10 @@ void TemplateDeclaration::semantic(Scope *sc)
/* Remember Scope for later instantiations, but make
* a copy since attributes can change.
*/
this->scope = new Scope(*sc);
this->scope->setNoFree();
if (!this->scope)
{ this->scope = new Scope(*sc);
this->scope->setNoFree();
}
// Set up scope for parameters
ScopeDsymbol *paramsym = new ScopeDsymbol();
@@ -697,21 +699,51 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
*/
for (size_t i = 0; i < dedtypes_dim; i++)
{
if (!dedtypes->data[i])
if (!(*dedtypes)[i])
{ assert(i < ti->tiargs->dim);
dedtypes->data[i] = ti->tiargs->data[i];
(*dedtypes)[i] = (Type *)(*ti->tiargs)[i];
}
}
}
#if DMDV2
if (m && constraint && !(flag & 1))
if (m && constraint && !flag)
{ /* Check to see if constraint is satisfied.
*/
makeParamNamesVisibleInConstraint(paramscope, fargs);
Expression *e = constraint->syntaxCopy();
paramscope->flags |= SCOPEstaticif;
e = e->semantic(paramscope);
e = e->optimize(WANTvalue | WANTinterpret);
Scope *sc = paramscope->push();
/* There's a chicken-and-egg problem here. We don't know yet if this template
* instantiation will be a local one (isnested is set), and we won't know until
* after selecting the correct template. Thus, function we're nesting inside
* is not on the sc scope chain, and this can cause errors in FuncDeclaration::getLevel().
* Workaround the problem by setting a flag to relax the checking on frame errors.
*/
sc->flags |= SCOPEstaticif;
FuncDeclaration *fd = onemember && onemember->toAlias() ?
onemember->toAlias()->isFuncDeclaration() : NULL;
Dsymbol *s = parent;
while (s->isTemplateInstance() || s->isTemplateMixin())
s = s->parent;
AggregateDeclaration *ad = s->isAggregateDeclaration();
VarDeclaration *vthissave;
if (fd && ad)
{
vthissave = fd->vthis;
fd->vthis = fd->declareThis(paramscope, ad);
}
e = e->semantic(sc);
if (e->op == TOKerror)
goto Lnomatch;
if (fd && fd->vthis)
fd->vthis = vthissave;
sc->pop();
e = e->ctfeInterpret();
if (e->isBool(TRUE))
;
else if (e->isBool(FALSE))
@@ -732,16 +764,16 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
{
for (size_t i = 0; i < dedtypes_dim; i++)
{
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
TemplateParameter *tp = (*parameters)[i];
Object *oarg;
printf(" [%d]", i);
if (i < ti->tiargs->dim)
oarg = (Object *)ti->tiargs->data[i];
oarg = (*ti->tiargs)[i];
else
oarg = NULL;
tp->print(oarg, (Object *)dedtypes->data[i]);
tp->print(oarg, (*dedtypes)[i]);
}
}
else
@@ -1299,12 +1331,71 @@ Lmatch:
#if DMDV2
if (constraint)
{ /* Check to see if constraint is satisfied.
* Most of this code appears twice; this is a good candidate for refactoring.
*/
makeParamNamesVisibleInConstraint(paramscope);
makeParamNamesVisibleInConstraint(paramscope, fargs);
Expression *e = constraint->syntaxCopy();
paramscope->flags |= SCOPEstaticif;
/* Detect recursive attempts to instantiate this template declaration,
* Bugzilla 4072
* void foo(T)(T x) if (is(typeof(foo(x)))) { }
* static assert(!is(typeof(foo(7))));
* Recursive attempts are regarded as a constraint failure.
*/
int nmatches = 0;
for (Previous *p = previous; p; p = p->prev)
{
if (arrayObjectMatch(p->dedargs, dedargs, this, sc))
{
//printf("recursive, no match p->sc=%p %p %s\n", p->sc, this, this->toChars());
/* It must be a subscope of p->sc, other scope chains are not recursive
* instantiations.
*/
for (Scope *scx = sc; scx; scx = scx->enclosing)
{
if (scx == p->sc)
goto Lnomatch;
}
}
/* BUG: should also check for ref param differences
*/
}
Previous pr;
pr.prev = previous;
pr.sc = paramscope;
pr.dedargs = dedargs;
previous = &pr; // add this to threaded list
int nerrors = global.errors;
FuncDeclaration *fd = onemember && onemember->toAlias() ?
onemember->toAlias()->isFuncDeclaration() : NULL;
Dsymbol *s = parent;
while (s->isTemplateInstance() || s->isTemplateMixin())
s = s->parent;
AggregateDeclaration *ad = s->isAggregateDeclaration();
VarDeclaration *vthissave;
if (fd && ad)
{
vthissave = fd->vthis;
fd->vthis = fd->declareThis(paramscope, ad);
}
e = e->semantic(paramscope);
e = e->optimize(WANTvalue | WANTinterpret);
if (fd && fd->vthis)
fd->vthis = vthissave;
previous = pr.prev; // unlink from threaded list
if (nerrors != global.errors) // if any errors from evaluating the constraint, no match
goto Lnomatch;
if (e->op == TOKerror)
goto Lnomatch;
e = e->ctfeInterpret();
if (e->isBool(TRUE))
;
else if (e->isBool(FALSE))
@@ -1317,8 +1408,8 @@ Lmatch:
#endif
#if 0
for (size_t i = 0; i < dedargs->dim; i++)
{ Type *t = (Type *)dedargs->data[i];
for (i = 0; i < dedargs->dim; i++)
{ Type *t = (*dedargs)[i];
printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars());
}
#endif
@@ -1363,6 +1454,12 @@ void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Obj
}
}
}
if (ea && ea->op == TOKtype)
targ = ea->type;
else if (ea && ea->op == TOKimport)
sa = ((ScopeExp *)ea)->sds;
else if (ea && (ea->op == TOKthis || ea->op == TOKsuper))
sa = ((ThisExp *)ea)->var;
if (targ)
{
@@ -1457,13 +1554,13 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
printf(" targsi:\n");
if (targsi)
{ for (size_t i = 0; i < targsi->dim; i++)
{ Object *arg = (Object *)targsi->data[i];
{ Object *arg = (*targsi)[i];
printf("\t%s\n", arg->toChars());
}
}
printf(" fargs:\n");
for (size_t i = 0; i < fargs->dim; i++)
{ Expression *arg = fargs->tdata()[i];
{ Expression *arg = (*fargs)[i];
printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
//printf("\tty = %d\n", arg->type->ty);
}
@@ -1483,10 +1580,9 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
goto Lerror;
}
MATCH m;
Objects dedargs;
m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs);
MATCH m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs);
//printf("deduceFunctionTemplateMatch = %d\n", m);
if (!m) // if no match
continue;
@@ -1524,7 +1620,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
td_best = td;
m_best = m;
tdargs->setDim(dedargs.dim);
memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *));
memcpy(tdargs->tdata(), dedargs.tdata(), tdargs->dim * sizeof(void *));
continue;
}
if (!td_best)
@@ -1575,7 +1671,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
{
if (i)
bufa.writeByte(',');
Object *oarg = args->tdata()[i];
Object *oarg = (*args)[i];
ObjectToCBuffer(&bufa, &hgs, oarg);
}
}
@@ -1583,7 +1679,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
OutBuffer buf;
argExpTypesToCBuffer(&buf, fargs, &hgs);
if (this->overnext)
::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)",
::error(this->loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)",
kind(), parent->toPrettyChars(), ident->toChars(),
bufa.toChars(), buf.toChars());
else
@@ -1979,7 +2075,7 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para
for (; 1; tupi++)
{ if (tupi == parameters->dim)
goto L1;
TemplateParameter *t = (TemplateParameter *)parameters->data[tupi];
TemplateParameter *t = (*parameters)[tupi];
TemplateTupleParameter *tup = t->isTemplateTupleParameter();
if (tup && tup->ident->equals(tid->ident))
break;
@@ -1992,7 +2088,7 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para
/* See if existing tuple, and whether it matches or not
*/
Object *o = (Object *)dedtypes->data[tupi];
Object *o = (*dedtypes)[tupi];
if (o)
{ // Existing deduced argument must be a tuple, and must match
Tuple *t = isTuple(o);
@@ -2000,7 +2096,7 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para
return MATCHnomatch;
for (size_t i = 0; i < tuple_dim; i++)
{ Parameter *arg = Parameter::getNth(this->parameters, nfparams - 1 + i);
if (!arg->type->equals((Object *)t->objects.data[i]))
if (!arg->type->equals(t->objects[i]))
return MATCHnomatch;
}
}
@@ -2010,9 +2106,9 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para
t->objects.setDim(tuple_dim);
for (size_t i = 0; i < tuple_dim; i++)
{ Parameter *arg = Parameter::getNth(this->parameters, nfparams - 1 + i);
t->objects.data[i] = (void *)arg->type;
t->objects[i] = arg->type;
}
dedtypes->data[tupi] = (void *)t;
(*dedtypes)[tupi] = t;
}
nfparams--; // don't consider the last parameter for type deduction
goto L2;
@@ -2043,8 +2139,8 @@ MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *pa
for (size_t i = 0; i < idents.dim; i++)
{
Identifier *id1 = (Identifier *)idents.data[i];
Identifier *id2 = (Identifier *)tp->idents.data[i];
Identifier *id1 = idents[i];
Identifier *id2 = tp->idents[i];
if (!id1->equals(id2))
return MATCHnomatch;
@@ -2082,7 +2178,19 @@ MATCH TypeInstance::deduceType(Scope *sc,
{ /* Didn't find it as a parameter identifier. Try looking
* it up and seeing if is an alias. See Bugzilla 1454
*/
Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
TypeIdentifier *tid = new TypeIdentifier(0, tp->tempinst->name);
Type *t;
Expression *e;
Dsymbol *s;
tid->resolve(0, sc, &e, &t, &s);
if (t)
{
s = t->toDsymbol(sc);
if (s)
{ TemplateInstance *ti = s->parent->isTemplateInstance();
s = ti ? ti->tempdecl : NULL;
}
}
if (s)
{
s = s->toAlias();
@@ -2092,7 +2200,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
}
goto Lnomatch;
}
TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
TemplateParameter *tpx = (*parameters)[i];
// This logic duplicates tpx->matchArg()
TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
if (!ta)
@@ -2102,14 +2210,14 @@ MATCH TypeInstance::deduceType(Scope *sc,
goto Lnomatch;
if (ta->specAlias && sa != ta->specAlias)
goto Lnomatch;
if (dedtypes->data[i])
if ((*dedtypes)[i])
{ // Must match already deduced symbol
Object *s = (Object *)dedtypes->data[i];
Object *s = (*dedtypes)[i];
if (s != sa)
goto Lnomatch;
}
dedtypes->data[i] = sa;
(*dedtypes)[i] = sa;
}
}
else if (tempinst->tempdecl != tp->tempinst->tempdecl)
@@ -2120,22 +2228,66 @@ MATCH TypeInstance::deduceType(Scope *sc,
for (size_t i = 0; 1; i++)
{
//printf("\ttest: tempinst->tiargs[%d]\n", i);
Object *o1;
Object *o1 = NULL;
if (i < tempinst->tiargs->dim)
o1 = (Object *)tempinst->tiargs->data[i];
o1 = (*tempinst->tiargs)[i];
else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim)
// Pick up default arg
o1 = (Object *)tempinst->tdtypes.data[i];
else
o1 = tempinst->tdtypes[i];
else if (i >= tp->tempinst->tiargs->dim)
break;
if (i >= tp->tempinst->tiargs->dim)
goto Lnomatch;
Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
Object *o2 = (*tp->tempinst->tiargs)[i];
Type *t2 = isType(o2);
int j;
if (t2 &&
t2->ty == Tident &&
i == tp->tempinst->tiargs->dim - 1 &&
(j = templateParameterLookup(t2, parameters), j != -1) &&
j == parameters->dim - 1 &&
(*parameters)[j]->isTemplateTupleParameter())
{
/* 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)
*/
/* Create tuple from remaining args
*/
Tuple *vt = new Tuple();
size_t vtdim = (tempinst->tempdecl->isVariadic()
? tempinst->tiargs->dim : tempinst->tdtypes.dim) - i;
vt->objects.setDim(vtdim);
for (size_t k = 0; k < vtdim; k++)
{
Object *o;
if (k < tempinst->tiargs->dim)
o = (*tempinst->tiargs)[i + k];
else // Pick up default arg
o = tempinst->tdtypes[i + k];
vt->objects[k] = o;
}
Tuple *v = (Tuple *)(*dedtypes)[j];
if (v)
{
if (!match(v, vt, tempinst->tempdecl, sc))
goto Lnomatch;
}
else
(*dedtypes)[j] = vt;
break; //return MATCHexact;
}
else if (!o1)
break;
Type *t1 = isType(o1);
Type *t2 = isType(o2);
Expression *e1 = isExpression(o1);
Expression *e2 = isExpression(o2);
@@ -2156,44 +2308,6 @@ MATCH TypeInstance::deduceType(Scope *sc,
if (v2) printf("v2 = %s\n", v2->toChars());
#endif
TemplateTupleParameter *ttp;
int j;
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();
size_t 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))
@@ -2201,6 +2315,12 @@ MATCH TypeInstance::deduceType(Scope *sc,
}
else if (e1 && e2)
{
Le:
e1 = e1->ctfeInterpret();
e2 = e2->ctfeInterpret();
//printf("e1 = %s, type = %s %d\n", e1->toChars(), e1->type->toChars(), e1->type->ty);
//printf("e2 = %s, type = %s %d\n", e2->toChars(), e2->type->toChars(), e2->type->ty);
if (!e1->equals(e2))
{ if (e2->op == TOKvar)
{
@@ -2210,6 +2330,12 @@ MATCH TypeInstance::deduceType(Scope *sc,
j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
goto L1;
}
if (!e2->implicitConvTo(e1->type))
goto Lnomatch;
e2 = e2->implicitCastTo(sc, e1->type);
e2 = e2->ctfeInterpret();
if (!e1->equals(e2))
goto Lnomatch;
}
}
@@ -2218,13 +2344,18 @@ MATCH TypeInstance::deduceType(Scope *sc,
j = templateParameterLookup(t2, parameters);
L1:
if (j == -1)
{
t2->resolve(loc, sc, &e2, &t2, &s2);
if (e2)
goto Le;
goto Lnomatch;
TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
}
TemplateParameter *tp = (*parameters)[j];
// BUG: use tp->matchArg() instead of the following
TemplateValueParameter *tv = tp->isTemplateValueParameter();
if (!tv)
goto Lnomatch;
Expression *e = (Expression *)dedtypes->data[j];
Expression *e = (Expression *)(*dedtypes)[j];
if (e)
{
if (!e1->equals(e))
@@ -2235,20 +2366,31 @@ MATCH TypeInstance::deduceType(Scope *sc,
MATCH m = (MATCH)e1->implicitConvTo(vt);
if (!m)
goto Lnomatch;
dedtypes->data[j] = e1;
(*dedtypes)[j] = e1;
}
}
else if (s1 && s2)
{
Ls:
if (!s1->equals(s2))
goto Lnomatch;
}
else if (s1 && t2 && t2->ty == Tident)
{
j = templateParameterLookup(t2, parameters);
if (j == -1)
{
t2->resolve(loc, sc, &e2, &t2, &s2);
if (s2)
goto Ls;
goto Lnomatch;
TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
}
TemplateParameter *tp = (*parameters)[j];
// BUG: use tp->matchArg() instead of the following
TemplateAliasParameter *ta = tp->isTemplateAliasParameter();
if (!ta)
goto Lnomatch;
Dsymbol *s = (Dsymbol *)dedtypes->data[j];
Dsymbol *s = (Dsymbol *)(*dedtypes)[j];
if (s)
{
if (!s1->equals(s))
@@ -2256,15 +2398,9 @@ MATCH TypeInstance::deduceType(Scope *sc,
}
else
{
dedtypes->data[j] = s1;
(*dedtypes)[j] = s1;
}
}
else if (s1 && s2)
{
if (!s1->equals(s2))
goto Lnomatch;
}
// BUG: Need to handle tuple parameters
else
goto Lnomatch;
}
@@ -2890,14 +3026,14 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc,
//printf("TemplateAliasParameter::matchArg()\n");
if (i < tiargs->dim)
oarg = tiargs->tdata()[i];
oarg = (*tiargs)[i];
else
{ // Get default argument instead
oarg = defaultArg(loc, sc);
if (!oarg)
{ assert(i < dedtypes->dim);
// It might have already been deduced
oarg = dedtypes->tdata()[i];
oarg = (*dedtypes)[i];
if (!oarg)
goto Lnomatch;
}
@@ -2911,23 +3047,33 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc,
{
if (!sa || sa == sdummy)
goto Lnomatch;
if (sa != specAlias)
if (sa != specAlias && isDsymbol(sa))
{
TemplateInstance *ti = isDsymbol(sa)->isTemplateInstance();
Type *ta = isType(specAlias);
if (!ti || !ta)
goto Lnomatch;
Type *t = new TypeInstance(0, ti);
MATCH m = t->deduceType(sc, ta, parameters, dedtypes);
if (m == MATCHnomatch)
goto Lnomatch;
}
}
else if (dedtypes->data[i])
else if ((*dedtypes)[i])
{ // Must match already deduced symbol
Dsymbol *s = (Dsymbol *)dedtypes->data[i];
Object *si = (*dedtypes)[i];
if (!sa || s != sa)
if (!sa || si != sa)
goto Lnomatch;
}
dedtypes->data[i] = sa;
(*dedtypes)[i] = sa;
*psparam = new AliasDeclaration(loc, ident, sa);
return MATCHexact;
Lnomatch:
*psparam = NULL;
//printf("\tm = %d\n", MATCHnomatch);
return MATCHnomatch;
}
@@ -3056,7 +3202,7 @@ void TemplateValueParameter::semantic(Scope *sc)
e = e->semantic(sc);
e = e->implicitCastTo(sc, valType);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
if (e->op == TOKint64 || e->op == TOKfloat64 ||
e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring)
specValue = e;
@@ -3069,7 +3215,7 @@ void TemplateValueParameter::semantic(Scope *sc)
e = e->semantic(sc);
e = e->implicitCastTo(sc, valType);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
if (e->op == TOKint64)
defaultValue = e;
//e->toInteger();
@@ -3141,11 +3287,11 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
e = e->semantic(sc);
e = e->implicitCastTo(sc, valType);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->ctfeInterpret();
ei = ei->syntaxCopy();
ei = ei->semantic(sc);
ei = ei->optimize(WANTvalue | WANTinterpret);
ei = ei->ctfeInterpret();
//printf("ei: %s, %s\n", ei->toChars(), ei->type->toChars());
//printf("e : %s, %s\n", e->toChars(), e->type->toChars());
if (!ei->equals(e))
@@ -3555,21 +3701,31 @@ void TemplateInstance::semantic(Scope *sc)
}
else
{
/* Run semantic on each argument, place results in tiargs[]
* (if we havetempdecl, then tiargs is already evaluated)
/* Find template declaration first.
*/
semanticTiargs(sc);
if (arrayObjectIsError(tiargs))
{ inst = this;
tempdecl = findTemplateDeclaration(sc);
if (!tempdecl)
{ if (!sc->parameterSpecialization)
inst = this;
//printf("error return %p, %d\n", tempdecl, global.errors);
return; // error recovery
}
tempdecl = findTemplateDeclaration(sc);
if (tempdecl)
tempdecl = findBestMatch(sc);
/* Run semantic on each argument, place results in tiargs[]
* (if we have tempdecl, then tiargs is already evaluated)
*/
semanticTiargs(sc);
if (arrayObjectIsError(tiargs))
{ if (!sc->parameterSpecialization)
inst = this;
//printf("error return %p, %d\n", tempdecl, global.errors);
return; // error recovery
}
tempdecl = findBestMatch(sc);
if (!tempdecl || global.errors)
{ inst = this;
{ if (!sc->parameterSpecialization)
inst = this;
//printf("error return %p, %d\n", tempdecl, global.errors);
return; // error recovery
}
@@ -3583,7 +3739,7 @@ void TemplateInstance::semantic(Scope *sc)
for (size_t i = 0; i < tempdecl->instances.dim; i++)
{
TemplateInstance *ti = (TemplateInstance *)tempdecl->instances.data[i];
TemplateInstance *ti = tempdecl->instances[i];
#if LOG
printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars());
#endif
@@ -3720,7 +3876,7 @@ void TemplateInstance::semantic(Scope *sc)
a->push(this);
break;
}
if (this == a->tdata()[i]) // if already in Array
if (this == (*a)[i]) // if already in Array
break;
}
}
@@ -3756,7 +3912,7 @@ void TemplateInstance::semantic(Scope *sc)
int memnum = 0;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
#if LOG
printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum);
#endif
@@ -3847,7 +4003,7 @@ void TemplateInstance::semantic(Scope *sc)
* or semantic3() yet.
*/
for (size_t i = 0; i < Module::deferred.dim; i++)
{ Dsymbol *sd = Module::deferred.tdata()[i];
{ Dsymbol *sd = Module::deferred[i];
if (sd->parent == this)
goto Laftersemantic;
@@ -3917,7 +4073,7 @@ void TemplateInstance::semantic(Scope *sc)
{
// Because we added 'this' in the last position above, we
// should be able to remove it without messing other indices up.
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
assert((*target_symbol_list)[target_symbol_list_idx] == this);
target_symbol_list->remove(target_symbol_list_idx);
}
semanticRun = PASSinit;
@@ -3953,12 +4109,12 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
return;
for (size_t j = 0; j < tiargs->dim; j++)
{
Object *o = (Object *)tiargs->data[j];
Object *o = (*tiargs)[j];
Type *ta = isType(o);
Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o);
//printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
//printf("1: (*tiargs)[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
if (ta)
{
//printf("type %s\n", ta->toChars());
@@ -3967,13 +4123,13 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
if (ea)
{
ea = ea->semantic(sc);
ea = ea->optimize(WANTvalue | WANTinterpret);
tiargs->data[j] = ea;
ea = ea->ctfeInterpret();
(*tiargs)[j] = ea;
}
else if (sa)
{
Ldsym:
tiargs->tdata()[j] = sa;
(*tiargs)[j] = sa;
TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
if (d)
{
@@ -3994,19 +4150,19 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
if (dim)
{ tiargs->reserve(dim);
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = tt->arguments->tdata()[i];
{ Parameter *arg = (*tt->arguments)[i];
tiargs->insert(j + i, arg->type);
}
}
j--;
}
else
tiargs->tdata()[j] = ta;
(*tiargs)[j] = ta;
}
else
{
assert(global.errors);
tiargs->data[j] = Type::terror;
(*tiargs)[j] = Type::terror;
}
}
else if (ea)
@@ -4017,8 +4173,8 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
}
assert(ea);
ea = ea->semantic(sc);
ea = ea->optimize(WANTvalue | WANTinterpret);
tiargs->data[j] = ea;
ea = ea->ctfeInterpret();
(*tiargs)[j] = ea;
if (ea->op == TOKtype)
{ ta = ea->type;
goto Ltype;
@@ -4047,13 +4203,13 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
{
assert(0);
}
//printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
//printf("1: (*tiargs)[%d] = %p\n", j, (*tiargs)[j]);
}
#if 0
printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
for (size_t j = 0; j < tiargs->dim; j++)
{
Object *o = (Object *)tiargs->data[j];
Object *o = (*tiargs)[j];
Type *ta = isType(o);
Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o);
@@ -4291,7 +4447,7 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
{
assert(ea);
ea = ea->castTo(tvp->valType);
ea = ea->optimize(WANTvalue | WANTinterpret);
ea = ea->ctfeInterpret();
tiargs->data[i] = (Object *)ea;
}
}
@@ -4444,7 +4600,7 @@ Identifier *TemplateInstance::genIdent()
}
else if (ea)
{
ea = ea->optimize(WANTvalue | WANTinterpret);
ea = ea->ctfeInterpret();
if (ea->op == TOKvar)
{
sa = ((VarExp *)ea)->var;
@@ -5359,10 +5515,14 @@ int TemplateMixin::hasPointers()
void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
//printf("TemplateMixin::setFieldOffset() %s\n", toChars());
if (scope) // if fwd reference
semantic(NULL); // try to resolve it
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
//printf("\t%s\n", s->toChars());
s->setFieldOffset(ad, poffset, isunion);
}
}