mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 10:16:36 +01:00
Merged 1.075 frontend.
This commit is contained in:
@@ -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
|
||||
|
||||
279
dmd/argtypes.c
279
dmd/argtypes.c
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
64
dmd/attrib.c
64
dmd/attrib.c
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
71
dmd/cast.c
71
dmd/cast.c
@@ -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);
|
||||
}
|
||||
|
||||
76
dmd/class.c
76
dmd/class.c
@@ -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;
|
||||
|
||||
10
dmd/cond.c
10
dmd/cond.c
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
17
dmd/doc.c
17
dmd/doc.c
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
166
dmd/expression.c
166
dmd/expression.c
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
492
dmd/func.c
492
dmd/func.c
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
36
dmd/import.c
36
dmd/import.c
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
67
dmd/init.c
67
dmd/init.c
@@ -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;
|
||||
}
|
||||
|
||||
13
dmd/init.h
13
dmd/init.h
@@ -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);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h> // memset()
|
||||
|
||||
#include "id.h"
|
||||
#include "init.h"
|
||||
|
||||
803
dmd/interpret.c
803
dmd/interpret.c
File diff suppressed because it is too large
Load Diff
44
dmd/lexer.c
44
dmd/lexer.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
21
dmd/mars.c
21
dmd/mars.c
@@ -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
|
||||
|
||||
15
dmd/mars.h
15
dmd/mars.h
@@ -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__
|
||||
|
||||
71
dmd/module.c
71
dmd/module.c
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
158
dmd/mtype.c
158
dmd/mtype.c
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
38
dmd/parse.c
38
dmd/parse.c
@@ -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;
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
#include "port.h"
|
||||
#include "root.h"
|
||||
#include "dchar.h"
|
||||
#include "rmem.h"
|
||||
|
||||
|
||||
|
||||
482
dmd/root/dchar.c
482
dmd/root/dchar.c
@@ -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
|
||||
194
dmd/root/dchar.h
194
dmd/root/dchar.h
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
118
dmd/root/root.c
118
dmd/root/root.c
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
|
||||
69
dmd/struct.c
69
dmd/struct.c
@@ -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);
|
||||
|
||||
436
dmd/template.c
436
dmd/template.c
@@ -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 = ≺ // 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user