mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-16 02:17:07 +02:00
Merged DMD 2.060 frontend.
Upstream Git tag v2.060 (e8fe11c20249cb9e42538be88c99b74ede4d12e3).
This commit is contained in:
+11
-4
@@ -67,7 +67,6 @@ 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
|
||||
int hasUnions; // set if aggregate has overlapping fields
|
||||
VarDeclarations fields; // VarDeclaration fields
|
||||
enum Sizeok sizeok; // set when structsize contains valid data
|
||||
@@ -96,17 +95,18 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
|
||||
#ifdef IN_GCC
|
||||
Expressions *attributes; // GCC decl/type attributes
|
||||
FuncDeclarations methods; // flat list of all methods for debug information
|
||||
#endif
|
||||
|
||||
Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this)
|
||||
|
||||
AggregateDeclaration(Loc loc, Identifier *id);
|
||||
void semantic2(Scope *sc);
|
||||
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
|
||||
@@ -165,8 +165,14 @@ struct StructDeclaration : AggregateDeclaration
|
||||
|
||||
FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals
|
||||
static FuncDeclaration *xerreq; // object.xopEquals
|
||||
|
||||
structalign_t alignment; // alignment applied outside of the struct
|
||||
#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);
|
||||
@@ -175,6 +181,7 @@ struct StructDeclaration : AggregateDeclaration
|
||||
char *mangle();
|
||||
const char *kind();
|
||||
void finalizeSize(Scope *sc);
|
||||
bool isPOD();
|
||||
#if DMDV1
|
||||
Expression *cloneMembers();
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "aggregate.h"
|
||||
#include "dsymbol.h"
|
||||
#include "mtype.h"
|
||||
#include "declaration.h"
|
||||
|
||||
#if DMDV2
|
||||
|
||||
@@ -78,9 +79,32 @@ void AliasThis::semantic(Scope *sc)
|
||||
::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
|
||||
else
|
||||
::error(loc, "undefined identifier %s", ident->toChars());
|
||||
return;
|
||||
}
|
||||
else if (ad->aliasthis && s != ad->aliasthis)
|
||||
error("there can be only one alias this");
|
||||
|
||||
/* disable the alias this conversion so the implicit conversion check
|
||||
* doesn't use it.
|
||||
*/
|
||||
/* This should use ad->aliasthis directly, but with static foreach and templates
|
||||
* ad->type->sym might be different to ad.
|
||||
*/
|
||||
AggregateDeclaration *ad2 = ad->type->toDsymbol(NULL)->isAggregateDeclaration();
|
||||
Dsymbol *save = ad2->aliasthis;
|
||||
ad2->aliasthis = NULL;
|
||||
|
||||
if (Declaration *d = s->isDeclaration())
|
||||
{
|
||||
Type *t = d->type;
|
||||
assert(t);
|
||||
if (ad->type->implicitConvTo(t))
|
||||
{
|
||||
::error(loc, "alias this is not reachable as %s already converts to %s", ad->toChars(), t->toChars());
|
||||
}
|
||||
}
|
||||
|
||||
ad2->aliasthis = save;
|
||||
ad->aliasthis = s;
|
||||
}
|
||||
else
|
||||
|
||||
+260
-12
@@ -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;
|
||||
@@ -124,23 +131,39 @@ TypeTuple *TypeBasic::toArgTypes()
|
||||
return t;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
TypeTuple *TypeVector::toArgTypes()
|
||||
{
|
||||
return new TypeTuple(Type::tfloat64);
|
||||
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()
|
||||
@@ -150,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()
|
||||
|
||||
+20
-4
@@ -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
|
||||
@@ -142,7 +142,6 @@ Expression *BinExp::arrayOp(Scope *sc)
|
||||
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
|
||||
#endif
|
||||
|
||||
size_t namelen = buf.offset;
|
||||
buf.writeByte(0);
|
||||
char *name = buf.toChars();
|
||||
Identifier *ident = Lexer::idPool(name);
|
||||
@@ -349,7 +348,7 @@ Expression *BinExp::arrayOp(Scope *sc)
|
||||
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
|
||||
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
|
||||
Statement *s1 = new ForStatement(0,
|
||||
new DeclarationStatement(0, d),
|
||||
new ExpStatement(0, d),
|
||||
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
|
||||
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
|
||||
new ExpStatement(0, loopbody));
|
||||
@@ -357,7 +356,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
|
||||
@@ -413,6 +412,23 @@ Expression *BinExp::arrayOp(Scope *sc)
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *BinAssignExp::arrayOp(Scope *sc)
|
||||
{
|
||||
//printf("BinAssignExp::arrayOp() %s\n", toChars());
|
||||
|
||||
/* Check that the elements of e1 can be assigned to
|
||||
*/
|
||||
Type *tn = e1->type->toBasetype()->nextOf();
|
||||
|
||||
if (tn && (!tn->isMutable() || !tn->isAssignable()))
|
||||
{
|
||||
error("slice %s is not mutable", e1->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
return BinExp::arrayOp(sc);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Construct the identifier for the array operation function,
|
||||
* and build the argument list to pass to it.
|
||||
|
||||
+53
-26
@@ -11,6 +11,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h> // memcpy()
|
||||
|
||||
#include "rmem.h"
|
||||
|
||||
@@ -37,7 +38,7 @@
|
||||
extern void obj_includelib(const char *name);
|
||||
|
||||
#if IN_DMD
|
||||
void obj_startaddress(Symbol *s);
|
||||
bool obj_startaddress(Symbol *s);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -760,7 +761,10 @@ void AlignDeclaration::semantic(Scope *sc)
|
||||
|
||||
void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->printf("align (%d)", salign);
|
||||
if (salign == STRUCTALIGN_DEFAULT)
|
||||
buf->printf("align");
|
||||
else
|
||||
buf->printf("align (%d)", salign);
|
||||
AttribDeclaration::toCBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
@@ -938,7 +942,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)
|
||||
@@ -977,8 +981,8 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
Expression *e = (*args)[i];
|
||||
|
||||
e = e->semantic(sc);
|
||||
if (e->op != TOKerror)
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->op != TOKerror && e->op != TOKtype)
|
||||
e = e->ctfeInterpret();
|
||||
if (e->op == TOKerror)
|
||||
{ errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
|
||||
return;
|
||||
@@ -1004,7 +1008,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;
|
||||
@@ -1022,7 +1026,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
goto Lnodecl;
|
||||
}
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
else if (ident == Id::GNU_asm)
|
||||
{
|
||||
if (! args || args->dim != 2)
|
||||
@@ -1046,7 +1050,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
|
||||
e = (*args)[1];
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
e = e->toString();
|
||||
if (e && ((StringExp *)e)->sz == 1)
|
||||
s = ((StringExp *)e);
|
||||
@@ -1068,7 +1072,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())
|
||||
@@ -1105,7 +1109,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
unsigned errors_save = global.errors;
|
||||
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
if (i == 0)
|
||||
printf(" (");
|
||||
else
|
||||
@@ -1175,21 +1179,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
|
||||
/* 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 (!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);
|
||||
}
|
||||
}
|
||||
#if DMDV2
|
||||
else if (ident == Id::startaddress)
|
||||
@@ -1406,6 +1408,31 @@ Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
|
||||
return dd;
|
||||
}
|
||||
|
||||
Dsymbols *StaticIfDeclaration::include(Scope *sc, ScopeDsymbol *sd)
|
||||
{
|
||||
//printf("StaticIfDeclaration::include(sc = %p) scope = %p\n", sc, scope);
|
||||
|
||||
if (condition->inc == 0)
|
||||
{
|
||||
Dsymbols *d = ConditionalDeclaration::include(sc, sd);
|
||||
|
||||
// Set the scopes lazily.
|
||||
if (scope && d)
|
||||
{
|
||||
for (size_t i = 0; i < d->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (*d)[i];
|
||||
|
||||
s->setScope(sc);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ConditionalDeclaration::include(sc, sd);
|
||||
}
|
||||
}
|
||||
|
||||
int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
@@ -1512,7 +1539,7 @@ void CompileDeclaration::compileIt(Scope *sc)
|
||||
//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());
|
||||
|
||||
+4
-3
@@ -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);
|
||||
@@ -122,7 +122,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);
|
||||
@@ -178,6 +178,7 @@ struct StaticIfDeclaration : ConditionalDeclaration
|
||||
|
||||
StaticIfDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
void semantic(Scope *sc);
|
||||
void importAll(Scope *sc);
|
||||
|
||||
+5
-5
@@ -10,9 +10,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h> // strcmp()
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#include "mars.h"
|
||||
#include "declaration.h"
|
||||
#include "attrib.h"
|
||||
@@ -44,10 +44,10 @@ enum BUILTIN FuncDeclaration::isBuiltin()
|
||||
{
|
||||
static const char FeZe [] = "FNaNbNfeZe"; // @safe pure nothrow real function(real)
|
||||
static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real)
|
||||
static const char FuintZint[] = "FNaNbkZi"; // pure nothrow int function(uint)
|
||||
static const char FuintZuint[] = "FNaNbkZk"; // pure nothrow uint function(uint)
|
||||
static const char FuintZint[] = "FNaNbNfkZi"; // @safe pure nothrow int function(uint)
|
||||
static const char FuintZuint[] = "FNaNbNfkZk"; // @safe pure nothrow uint function(uint)
|
||||
static const char FulongZulong[] = "FNaNbkZk"; // pure nothrow int function(ulong)
|
||||
static const char FulongZint[] = "FNaNbmZi"; // pure nothrow int function(uint)
|
||||
static const char FulongZint[] = "FNaNbNfmZi"; // @safe pure nothrow int function(uint)
|
||||
static const char FrealrealZreal [] = "FNaNbNfeeZe"; // @safe pure nothrow real function(real, real)
|
||||
static const char FrealZlong [] = "FNaNbNfeZl"; // @safe pure nothrow long function(real)
|
||||
|
||||
@@ -167,7 +167,7 @@ uinteger_t eval_bswap(Expression *arg0)
|
||||
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments)
|
||||
{
|
||||
assert(arguments && arguments->dim);
|
||||
Expression *arg0 = arguments->tdata()[0];
|
||||
Expression *arg0 = (*arguments)[0];
|
||||
Expression *e = NULL;
|
||||
switch (builtin)
|
||||
{
|
||||
|
||||
+4
-3
@@ -42,6 +42,7 @@ struct CanThrow
|
||||
|
||||
int Expression::canThrow(bool mustNotThrow)
|
||||
{
|
||||
//printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars());
|
||||
CanThrow ct;
|
||||
ct.can = FALSE;
|
||||
ct.mustnot = mustNotThrow;
|
||||
@@ -132,7 +133,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
||||
{
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
{
|
||||
s = decl->tdata()[i];
|
||||
s = (*decl)[i];
|
||||
if (Dsymbol_canThrow(s, mustNotThrow))
|
||||
return 1;
|
||||
}
|
||||
@@ -165,7 +166,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
||||
{
|
||||
for (size_t i = 0; i < tm->members->dim; i++)
|
||||
{
|
||||
Dsymbol *sm = tm->members->tdata()[i];
|
||||
Dsymbol *sm = (*tm->members)[i];
|
||||
if (Dsymbol_canThrow(sm, mustNotThrow))
|
||||
return 1;
|
||||
}
|
||||
@@ -174,7 +175,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
||||
else if ((td = s->isTupleDeclaration()) != NULL)
|
||||
{
|
||||
for (size_t i = 0; i < td->objects->dim; i++)
|
||||
{ Object *o = td->objects->tdata()[i];
|
||||
{ Object *o = (*td->objects)[i];
|
||||
if (o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{ Expression *eo = (Expression *)o;
|
||||
if (eo->op == TOKdsymbol)
|
||||
|
||||
+108
-32
@@ -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"
|
||||
|
||||
@@ -36,9 +37,10 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
|
||||
|
||||
MATCH match = implicitConvTo(t);
|
||||
if (match)
|
||||
{ TY tyfrom = type->toBasetype()->ty;
|
||||
TY tyto = t->toBasetype()->ty;
|
||||
{
|
||||
#if DMDV1
|
||||
TY tyfrom = type->toBasetype()->ty;
|
||||
TY tyto = t->toBasetype()->ty;
|
||||
if (global.params.warnings &&
|
||||
Type::impcnvWarn[tyfrom][tyto] &&
|
||||
op != TOKint64)
|
||||
@@ -138,7 +140,7 @@ Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t)
|
||||
Expression *FuncExp::implicitCastTo(Scope *sc, Type *t)
|
||||
{
|
||||
//printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
|
||||
return inferType(t);
|
||||
return inferType(t)->Expression::implicitCastTo(sc, t);
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
@@ -215,6 +217,7 @@ MATCH IntegerExp::implicitConvTo(Type *t)
|
||||
|
||||
TY ty = type->toBasetype()->ty;
|
||||
TY toty = t->toBasetype()->ty;
|
||||
TY oldty = ty;
|
||||
|
||||
if (m == MATCHnomatch && t->ty == Tenum)
|
||||
goto Lno;
|
||||
@@ -282,6 +285,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)
|
||||
@@ -293,6 +298,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;
|
||||
@@ -319,11 +327,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;
|
||||
@@ -540,19 +543,28 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t)
|
||||
if ((tb->ty == Tarray || tb->ty == Tsarray) &&
|
||||
(typeb->ty == Tarray || typeb->ty == Tsarray))
|
||||
{
|
||||
Type *typen = typeb->nextOf()->toBasetype();
|
||||
|
||||
if (tb->ty == Tsarray)
|
||||
{ TypeSArray *tsa = (TypeSArray *)tb;
|
||||
if (elements->dim != tsa->dim->toInteger())
|
||||
result = MATCHnomatch;
|
||||
}
|
||||
|
||||
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
|
||||
Type *telement = tb->nextOf();
|
||||
if (!elements->dim)
|
||||
{ if (typen->ty != Tvoid)
|
||||
result = typen->implicitConvTo(telement);
|
||||
}
|
||||
else
|
||||
{ for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (*elements)[i];
|
||||
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)
|
||||
@@ -560,25 +572,46 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t)
|
||||
|
||||
return result;
|
||||
}
|
||||
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;
|
||||
}
|
||||
else
|
||||
return Expression::implicitConvTo(t);
|
||||
}
|
||||
|
||||
MATCH AssocArrayLiteralExp::implicitConvTo(Type *t)
|
||||
{ MATCH result = MATCHexact;
|
||||
|
||||
{
|
||||
Type *typeb = type->toBasetype();
|
||||
Type *tb = t->toBasetype();
|
||||
if (tb->ty == Taarray && typeb->ty == Taarray)
|
||||
{
|
||||
MATCH result = MATCHexact;
|
||||
for (size_t i = 0; i < keys->dim; i++)
|
||||
{ Expression *e = keys->tdata()[i];
|
||||
{ Expression *e = (*keys)[i];
|
||||
MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->index);
|
||||
if (m < result)
|
||||
result = m; // remember worst match
|
||||
if (result == MATCHnomatch)
|
||||
break; // no need to check for worse
|
||||
e = values->tdata()[i];
|
||||
e = (*values)[i];
|
||||
m = (MATCH)e->implicitConvTo(tb->nextOf());
|
||||
if (m < result)
|
||||
result = m; // remember worst match
|
||||
@@ -905,6 +938,9 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
}
|
||||
else if (tb->ty == Tvector && typeb->ty != Tvector)
|
||||
{
|
||||
//printf("test1 e = %s, e->type = %s, tb = %s\n", e->toChars(), e->type->toChars(), tb->toChars());
|
||||
TypeVector *tv = (TypeVector *)tb;
|
||||
e = new CastExp(loc, e, tv->elementType());
|
||||
e = new VectorExp(loc, e, tb);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
@@ -1372,9 +1408,9 @@ Expression *TupleExp::castTo(Scope *sc, Type *t)
|
||||
{ TupleExp *e = (TupleExp *)copy();
|
||||
e->exps = (Expressions *)exps->copy();
|
||||
for (size_t i = 0; i < e->exps->dim; i++)
|
||||
{ Expression *ex = e->exps->tdata()[i];
|
||||
{ Expression *ex = (*e->exps)[i];
|
||||
ex = ex->castTo(sc, t);
|
||||
e->exps->tdata()[i] = ex;
|
||||
(*e->exps)[i] = ex;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
@@ -1420,6 +1456,28 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
|
||||
e->type = tp;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
L1:
|
||||
return e->Expression::castTo(sc, t);
|
||||
}
|
||||
@@ -1439,13 +1497,13 @@ Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
|
||||
e->values = (Expressions *)values->copy();
|
||||
assert(keys->dim == values->dim);
|
||||
for (size_t i = 0; i < keys->dim; i++)
|
||||
{ Expression *ex = values->tdata()[i];
|
||||
{ Expression *ex = (*values)[i];
|
||||
ex = ex->castTo(sc, tb->nextOf());
|
||||
e->values->tdata()[i] = ex;
|
||||
(*e->values)[i] = ex;
|
||||
|
||||
ex = keys->tdata()[i];
|
||||
ex = (*keys)[i];
|
||||
ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
|
||||
e->keys->tdata()[i] = ex;
|
||||
(*e->keys)[i] = ex;
|
||||
}
|
||||
e->type = t;
|
||||
return e;
|
||||
@@ -1688,7 +1746,7 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
|
||||
{
|
||||
if (to->ty == Tdelegate ||
|
||||
to->ty == Tpointer && to->nextOf()->ty == Tfunction)
|
||||
{ treq = to;
|
||||
{ fd->treq = to;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -1714,6 +1772,8 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
|
||||
{
|
||||
TypeFunction *tfv = (TypeFunction *)t;
|
||||
TypeFunction *tfl = (TypeFunction *)fd->type;
|
||||
//printf("\ttfv = %s\n", tfv->toChars());
|
||||
//printf("\ttfl = %s\n", tfl->toChars());
|
||||
size_t dim = Parameter::dim(tfl->parameters);
|
||||
|
||||
if (Parameter::dim(tfv->parameters) == dim &&
|
||||
@@ -1740,6 +1800,13 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
|
||||
}
|
||||
}
|
||||
|
||||
// Set target of return type inference
|
||||
assert(td->onemember);
|
||||
FuncLiteralDeclaration *fld = td->onemember->isFuncLiteralDeclaration();
|
||||
assert(fld);
|
||||
if (!fld->type->nextOf() && tfv->next)
|
||||
fld->treq = tfv;
|
||||
|
||||
TemplateInstance *ti = new TemplateInstance(loc, td, tiargs);
|
||||
e = (new ScopeExp(loc, ti))->semantic(td->scope);
|
||||
if (e->op == TOKfunction)
|
||||
@@ -1759,14 +1826,12 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
|
||||
to->ty == Tdelegate)
|
||||
{
|
||||
Type *typen = type->nextOf();
|
||||
assert(typen->deco);
|
||||
//if (typen->covariant(to->nextOf()) == 1)
|
||||
if (typen->deco)
|
||||
{
|
||||
FuncExp *fe = (FuncExp *)copy();
|
||||
fe->tok = TOKdelegate;
|
||||
fe->type = (new TypeDelegate(typen))->merge();
|
||||
e = fe;
|
||||
//e = fe->Expression::implicitCastTo(sc, to);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1879,7 +1944,7 @@ bool isVoidArrayLiteral(Expression *e, Type *other)
|
||||
while (e->op == TOKarrayliteral && e->type->ty == Tarray
|
||||
&& (((ArrayLiteralExp *)e)->elements->dim == 1))
|
||||
{
|
||||
e = ((ArrayLiteralExp *)e)->elements->tdata()[0];
|
||||
e = (*((ArrayLiteralExp *)e)->elements)[0];
|
||||
if (other->ty == Tsarray || other->ty == Tarray)
|
||||
other = other->nextOf();
|
||||
else
|
||||
@@ -1910,6 +1975,7 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
|
||||
//printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars());
|
||||
//e->dump(0);
|
||||
|
||||
MATCH m;
|
||||
Expression *e1 = *pe1;
|
||||
Expression *e2 = *pe2;
|
||||
|
||||
@@ -2110,10 +2176,20 @@ Lagain:
|
||||
*/
|
||||
goto Lx2;
|
||||
}
|
||||
else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2))
|
||||
else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
|
||||
(m = t1->implicitConvTo(t2)) != MATCHnomatch)
|
||||
{
|
||||
if (t1->ty == Tsarray && e2->op == TOKarrayliteral)
|
||||
goto Lt1;
|
||||
if (m == MATCHconst &&
|
||||
(e->op == TOKaddass || e->op == TOKminass || e->op == TOKmulass ||
|
||||
e->op == TOKdivass || e->op == TOKmodass || e->op == TOKpowass ||
|
||||
e->op == TOKandass || e->op == TOKorass || e->op == TOKxorass)
|
||||
)
|
||||
{ // Don't make the lvalue const
|
||||
t = t2;
|
||||
goto Lret;
|
||||
}
|
||||
goto Lt2;
|
||||
}
|
||||
else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1))
|
||||
|
||||
+64
-47
@@ -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"
|
||||
@@ -177,6 +178,12 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
|
||||
Type::typeinfowild->error("%s", msg);
|
||||
Type::typeinfowild = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Vector)
|
||||
{ if (Type::typeinfovector)
|
||||
Type::typeinfovector->error("%s", msg);
|
||||
Type::typeinfovector = this;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -241,9 +248,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);
|
||||
@@ -292,10 +299,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
scope = NULL;
|
||||
}
|
||||
unsigned dprogress_save = Module::dprogress;
|
||||
#ifdef IN_GCC
|
||||
methods.setDim(0);
|
||||
#endif
|
||||
|
||||
int errors = global.gaggedErrors;
|
||||
|
||||
if (sc->stc & STCdeprecated)
|
||||
@@ -308,7 +311,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();
|
||||
|
||||
@@ -333,7 +336,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)
|
||||
@@ -403,7 +406,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)
|
||||
@@ -432,7 +435,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());
|
||||
}
|
||||
@@ -464,22 +467,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;
|
||||
@@ -535,7 +536,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())
|
||||
{
|
||||
@@ -614,8 +617,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
sc->protection = PROTpublic;
|
||||
sc->explicitProtection = 0;
|
||||
sc->structalign = 8;
|
||||
structalign = sc->structalign;
|
||||
sc->structalign = STRUCTALIGN_DEFAULT;
|
||||
if (baseClass)
|
||||
{ sc->offset = baseClass->structsize;
|
||||
alignsize = baseClass->alignsize;
|
||||
@@ -642,9 +644,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);
|
||||
}
|
||||
}
|
||||
@@ -682,7 +685,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
fields.setDim(0);
|
||||
structsize = 0;
|
||||
alignsize = 0;
|
||||
structalign = 0;
|
||||
// structalign = 0;
|
||||
|
||||
sc = sc->pop();
|
||||
|
||||
@@ -757,7 +760,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
BaseClass *b = (*vtblInterfaces)[i];
|
||||
unsigned thissize = PTRSIZE;
|
||||
|
||||
alignmember(structalign, thissize, &sc->offset);
|
||||
alignmember(STRUCTALIGN_DEFAULT, thissize, &sc->offset);
|
||||
assert(b->offset == 0);
|
||||
b->offset = sc->offset;
|
||||
|
||||
@@ -774,9 +777,12 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
structsize = sc->offset;
|
||||
#if IN_LLVM
|
||||
if (global.params.is64bit)
|
||||
structsize = (structsize + structalign - 1) & ~(structalign - 1);
|
||||
if (sc->structalign == STRUCTALIGN_DEFAULT)
|
||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||
else
|
||||
structsize = (structsize + sc->structalign - 1) & ~(sc->structalign - 1);
|
||||
#endif
|
||||
|
||||
sizeok = SIZEOKdone;
|
||||
Module::dprogress++;
|
||||
|
||||
@@ -788,7 +794,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);
|
||||
}
|
||||
@@ -813,7 +819,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(',');
|
||||
@@ -827,7 +833,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);
|
||||
@@ -862,7 +868,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;
|
||||
@@ -908,7 +914,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;
|
||||
}
|
||||
@@ -946,7 +952,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)
|
||||
{
|
||||
@@ -1011,7 +1017,7 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
|
||||
if (os)
|
||||
{
|
||||
for (size_t i = 0; i < os->a.dim; i++)
|
||||
{ Dsymbol *s2 = os->a.tdata()[i];
|
||||
{ Dsymbol *s2 = os->a[i];
|
||||
FuncDeclaration *f2 = s2->isFuncDeclaration();
|
||||
if (f2 && overloadApply(f2, &isf, fd))
|
||||
return 0;
|
||||
@@ -1054,9 +1060,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
|
||||
@@ -1068,6 +1076,15 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
|
||||
goto Lfdmatch;
|
||||
}
|
||||
|
||||
{
|
||||
int m1 = (tf->mod == fd ->type->mod) ? MATCHexact : MATCHnomatch;
|
||||
int m2 = (tf->mod == fdmatch->type->mod) ? MATCHexact : MATCHnomatch;
|
||||
if (m1 > m2)
|
||||
goto Lfd;
|
||||
else if (m1 < m2)
|
||||
goto Lfdmatch;
|
||||
}
|
||||
|
||||
{
|
||||
// The way of definition: non-mixin > mixin
|
||||
int m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
|
||||
@@ -1158,7 +1175,7 @@ int ClassDeclaration::isAbstract()
|
||||
return TRUE;
|
||||
for (size_t i = 1; i < vtbl.dim; i++)
|
||||
{
|
||||
FuncDeclaration *fd = vtbl.tdata()[i]->isFuncDeclaration();
|
||||
FuncDeclaration *fd = vtbl[i]->isFuncDeclaration();
|
||||
|
||||
//printf("\tvtbl[%d] = %p\n", i, fd);
|
||||
if (!fd || fd->isAbstract())
|
||||
@@ -1266,7 +1283,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();
|
||||
|
||||
@@ -1294,7 +1311,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)
|
||||
@@ -1312,7 +1329,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());
|
||||
}
|
||||
@@ -1373,7 +1390,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
vtbl.reserve(d - 1);
|
||||
for (size_t j = 1; j < d; j++)
|
||||
vtbl.push(b->base->vtbl.tdata()[j]);
|
||||
vtbl.push(b->base->vtbl[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1401,10 +1418,10 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
sc->linkage = LINKwindows;
|
||||
else if (isCPPinterface())
|
||||
sc->linkage = LINKcpp;
|
||||
sc->structalign = 8;
|
||||
sc->structalign = STRUCTALIGN_DEFAULT;
|
||||
sc->protection = PROTpublic;
|
||||
sc->explicitProtection = 0;
|
||||
structalign = sc->structalign;
|
||||
// structalign = sc->structalign;
|
||||
sc->offset = PTRSIZE * 2;
|
||||
structsize = sc->offset;
|
||||
inuse++;
|
||||
@@ -1426,7 +1443,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->semantic(sc);
|
||||
}
|
||||
|
||||
@@ -1526,7 +1543,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;
|
||||
}
|
||||
@@ -1610,7 +1627,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 = base->vtbl.tdata()[j]->isFuncDeclaration();
|
||||
FuncDeclaration *ifd = base->vtbl[j]->isFuncDeclaration();
|
||||
FuncDeclaration *fd;
|
||||
TypeFunction *tf;
|
||||
|
||||
@@ -1647,7 +1664,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins
|
||||
fd = NULL;
|
||||
}
|
||||
if (vtbl)
|
||||
vtbl->tdata()[j] = fd;
|
||||
(*vtbl)[j] = fd;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
+16
-16
@@ -45,7 +45,7 @@ int StructDeclaration::needOpAssign()
|
||||
*/
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields.tdata()[i];
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
@@ -153,7 +153,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
||||
//printf("\tmemberwise copy\n");
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields.tdata()[i];
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
// this.v = s.v;
|
||||
@@ -214,7 +214,7 @@ int StructDeclaration::needOpEquals()
|
||||
*/
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields.tdata()[i];
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
@@ -304,7 +304,7 @@ FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
|
||||
//printf("\tmemberwise compare\n");
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields.tdata()[i];
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
@@ -513,13 +513,13 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields.tdata()[i];
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
dinteger_t dim = (tv->ty == Tsarray ? 1 : 0);
|
||||
dinteger_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
@@ -528,7 +528,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->postblit)
|
||||
if (sd->postblit && dim)
|
||||
{
|
||||
stc |= sd->postblit->storage_class & STCdisable;
|
||||
|
||||
@@ -542,7 +542,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 0)
|
||||
if (v->type->toBasetype()->ty == Tstruct)
|
||||
{ // this.v.postblit()
|
||||
ex = new DotVarExp(0, ex, sd->postblit, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
@@ -581,12 +581,12 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return postblits.tdata()[0];
|
||||
return postblits[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < postblits.dim; i++)
|
||||
{ FuncDeclaration *fd = postblits.tdata()[i];
|
||||
{ FuncDeclaration *fd = postblits[i];
|
||||
stc |= fd->storage_class & STCdisable;
|
||||
if (stc & STCdisable)
|
||||
{
|
||||
@@ -625,13 +625,13 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
||||
#if DMDV2
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields.tdata()[i];
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
dinteger_t dim = (tv->ty == Tsarray ? 1 : 0);
|
||||
dinteger_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
@@ -640,14 +640,14 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
if (sd->dtor && dim)
|
||||
{ Expression *ex;
|
||||
|
||||
// this.v
|
||||
ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, v, 0);
|
||||
|
||||
if (dim == 0)
|
||||
if (v->type->toBasetype()->ty == Tstruct)
|
||||
{ // this.v.dtor()
|
||||
ex = new DotVarExp(0, ex, sd->dtor, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
@@ -686,12 +686,12 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
||||
return NULL;
|
||||
|
||||
case 1:
|
||||
return dtors.tdata()[0];
|
||||
return dtors[0];
|
||||
|
||||
default:
|
||||
e = NULL;
|
||||
for (size_t i = 0; i < dtors.dim; i++)
|
||||
{ FuncDeclaration *fd = dtors.tdata()[i];
|
||||
{ FuncDeclaration *fd = dtors[i];
|
||||
Expression *ex = new ThisExp(0);
|
||||
ex = new DotVarExp(0, ex, fd, 0);
|
||||
ex = new CallExp(0, ex);
|
||||
|
||||
+9
-1
@@ -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;
|
||||
|
||||
+55
-12
@@ -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__
|
||||
@@ -621,7 +622,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
|
||||
// Special case: call sqrt directly.
|
||||
Expressions args;
|
||||
args.setDim(1);
|
||||
args.tdata()[0] = e1;
|
||||
args[0] = e1;
|
||||
e = eval_builtin(loc, BUILTINsqrt, &args);
|
||||
if (!e)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
@@ -1290,7 +1291,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);
|
||||
|
||||
@@ -1374,7 +1375,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;
|
||||
@@ -1392,7 +1393,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;
|
||||
@@ -1407,12 +1408,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;
|
||||
@@ -1483,7 +1484,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;
|
||||
}
|
||||
@@ -1512,7 +1513,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);
|
||||
}
|
||||
}
|
||||
@@ -1525,7 +1526,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;
|
||||
@@ -1549,6 +1550,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)
|
||||
@@ -1666,7 +1709,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;
|
||||
@@ -1684,7 +1727,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;
|
||||
|
||||
+6
-5
@@ -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
|
||||
@@ -9,6 +9,7 @@
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
@@ -69,7 +70,7 @@ int CppMangleState::substitute(OutBuffer *buf, void *p)
|
||||
{
|
||||
for (size_t i = 0; i < components.dim; i++)
|
||||
{
|
||||
if (p == components.tdata()[i])
|
||||
if (p == components[i])
|
||||
{
|
||||
/* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
|
||||
*/
|
||||
@@ -88,7 +89,7 @@ int CppMangleState::exist(void *p)
|
||||
{
|
||||
for (size_t i = 0; i < components.dim; i++)
|
||||
{
|
||||
if (p == components.tdata()[i])
|
||||
if (p == components[i])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -160,7 +161,7 @@ char *cpp_mangle(Dsymbol *s)
|
||||
cms.components.setDim(0);
|
||||
|
||||
OutBuffer buf;
|
||||
#if MACHOBJ
|
||||
#if TARGET_OSX
|
||||
buf.writestring("__Z");
|
||||
#else
|
||||
buf.writestring("_Z");
|
||||
@@ -417,7 +418,7 @@ void Parameter::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *a
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Parameter *arg = arguments->tdata()[i];
|
||||
{ Parameter *arg = (*arguments)[i];
|
||||
Type *t = arg->type;
|
||||
if (arg->storageClass & (STCout | STCref))
|
||||
t = t->referenceTo();
|
||||
|
||||
+119
-59
@@ -122,6 +122,18 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
|
||||
}
|
||||
#endif
|
||||
|
||||
Dsymbol *Declaration::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
Dsymbol *s = Dsymbol::search(loc, ident, flags);
|
||||
if (!s && type)
|
||||
{
|
||||
s = type->toDsymbol(NULL);
|
||||
if (s)
|
||||
s = s->search(loc, ident, flags);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/********************************* TupleDeclaration ****************************/
|
||||
|
||||
@@ -159,7 +171,7 @@ Type *TupleDeclaration::getType()
|
||||
/* It's only a type tuple if all the Object's are types
|
||||
*/
|
||||
for (size_t i = 0; i < objects->dim; i++)
|
||||
{ Object *o = objects->tdata()[i];
|
||||
{ Object *o = (*objects)[i];
|
||||
|
||||
if (o->dyncast() != DYNCAST_TYPE)
|
||||
{
|
||||
@@ -176,7 +188,7 @@ Type *TupleDeclaration::getType()
|
||||
OutBuffer buf;
|
||||
int hasdeco = 1;
|
||||
for (size_t i = 0; i < types->dim; i++)
|
||||
{ Type *t = types->tdata()[i];
|
||||
{ Type *t = (*types)[i];
|
||||
|
||||
//printf("type = %s\n", t->toChars());
|
||||
#if 0
|
||||
@@ -187,7 +199,7 @@ Type *TupleDeclaration::getType()
|
||||
#else
|
||||
Parameter *arg = new Parameter(0, t, NULL, NULL);
|
||||
#endif
|
||||
args->tdata()[i] = arg;
|
||||
(*args)[i] = arg;
|
||||
if (!t->deco)
|
||||
hasdeco = 0;
|
||||
}
|
||||
@@ -204,7 +216,7 @@ int TupleDeclaration::needThis()
|
||||
{
|
||||
//printf("TupleDeclaration::needThis(%s)\n", toChars());
|
||||
for (size_t i = 0; i < objects->dim; i++)
|
||||
{ Object *o = objects->tdata()[i];
|
||||
{ Object *o = (*objects)[i];
|
||||
if (o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{ Expression *e = (Expression *)o;
|
||||
if (e->op == TOKdsymbol)
|
||||
@@ -336,7 +348,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;
|
||||
@@ -557,6 +569,17 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
s->parent = sc->parent;
|
||||
}
|
||||
}
|
||||
OverloadSet *o = s->toAlias()->isOverloadSet();
|
||||
if (o)
|
||||
{
|
||||
if (overnext)
|
||||
{
|
||||
o->push(overnext);
|
||||
overnext = NULL;
|
||||
s = o;
|
||||
s->parent = sc->parent;
|
||||
}
|
||||
}
|
||||
if (overnext)
|
||||
ScopeDsymbol::multiplyDefined(0, this, overnext);
|
||||
if (s == this)
|
||||
@@ -619,7 +642,9 @@ const char *AliasDeclaration::kind()
|
||||
|
||||
Type *AliasDeclaration::getType()
|
||||
{
|
||||
return type;
|
||||
if (type)
|
||||
return type;
|
||||
return toAlias()->getType();
|
||||
}
|
||||
|
||||
Dsymbol *AliasDeclaration::toAlias()
|
||||
@@ -632,7 +657,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;
|
||||
@@ -845,6 +872,14 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
this->parent = sc->parent;
|
||||
//printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
|
||||
protection = sc->protection;
|
||||
|
||||
/* If scope's alignment is the default, use the type's alignment,
|
||||
* otherwise the scope overrrides.
|
||||
*/
|
||||
alignment = sc->structalign;
|
||||
if (alignment == STRUCTALIGN_DEFAULT)
|
||||
alignment = type->alignment(); // use type's alignment
|
||||
|
||||
//printf("sc->stc = %x\n", sc->stc);
|
||||
//printf("storage_class = x%x\n", storage_class);
|
||||
|
||||
@@ -931,7 +966,7 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
for (size_t pos = 0; pos < iexps->dim; pos++)
|
||||
{
|
||||
Lexpand1:
|
||||
Expression *e = iexps->tdata()[pos];
|
||||
Expression *e = (*iexps)[pos];
|
||||
Parameter *arg = Parameter::getNth(tt->arguments, pos);
|
||||
arg->type = arg->type->semantic(loc, sc);
|
||||
//printf("[%d] iexps->dim = %d, ", pos, iexps->dim);
|
||||
@@ -1028,7 +1063,7 @@ Lnomatch:
|
||||
|
||||
Expression *einit = ie;
|
||||
if (ie && ie->op == TOKtuple)
|
||||
{ einit = ((TupleExp *)ie)->exps->tdata()[i];
|
||||
{ einit = (*((TupleExp *)ie)->exps)[i];
|
||||
}
|
||||
Initializer *ti = init;
|
||||
if (einit)
|
||||
@@ -1051,7 +1086,7 @@ Lnomatch:
|
||||
}
|
||||
#endif
|
||||
Expression *e = new DsymbolExp(loc, v);
|
||||
exps->tdata()[i] = e;
|
||||
(*exps)[i] = e;
|
||||
}
|
||||
TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
|
||||
v2->isexp = 1;
|
||||
@@ -1091,7 +1126,7 @@ Lnomatch:
|
||||
}
|
||||
else if (storage_class & STCfinal)
|
||||
{
|
||||
error("final cannot be applied to variable");
|
||||
error("final cannot be applied to variable, perhaps you meant const?");
|
||||
}
|
||||
|
||||
if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe))
|
||||
@@ -1114,7 +1149,6 @@ Lnomatch:
|
||||
#endif
|
||||
{
|
||||
storage_class |= STCfield;
|
||||
alignment = sc->structalign;
|
||||
#if DMDV2
|
||||
if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor ||
|
||||
tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor)
|
||||
@@ -1244,6 +1278,19 @@ Lnomatch:
|
||||
init = new ExpInitializer(loc, e);
|
||||
goto Ldtor;
|
||||
}
|
||||
else if (type->ty == Tstruct &&
|
||||
(((TypeStruct *)type)->sym->isnested))
|
||||
{
|
||||
/* Nested struct requires valid enclosing frame pointer.
|
||||
* In StructLiteralExp::toElem(), it's calculated.
|
||||
*/
|
||||
Expression *e = type->defaultInitLiteral(loc);
|
||||
Expression *e1 = new VarExp(loc, this);
|
||||
e = new ConstructExp(loc, e1, e);
|
||||
e = e->semantic(sc);
|
||||
init = new ExpInitializer(loc, e);
|
||||
goto Ldtor;
|
||||
}
|
||||
else if (type->ty == Ttypedef)
|
||||
{ TypeTypedef *td = (TypeTypedef *)type;
|
||||
if (td->sym->init)
|
||||
@@ -1313,7 +1360,8 @@ Lnomatch:
|
||||
Expression *e = init->toExpression();
|
||||
if (!e)
|
||||
{
|
||||
init = init->semantic(sc, type, 0); // Don't need to interpret
|
||||
// Run semantic, but 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");
|
||||
@@ -1395,16 +1443,26 @@ Lnomatch:
|
||||
{
|
||||
e = new ConstructExp(loc, new VarExp(loc, this), new IntegerExp(loc, 0, Type::tint32));
|
||||
}
|
||||
else if (sd->isNested())
|
||||
{ e = new AssignExp(loc, new VarExp(loc, this), t->defaultInitLiteral(loc));
|
||||
e->op = TOKblit;
|
||||
}
|
||||
else
|
||||
{ e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc));
|
||||
e->op = TOKblit;
|
||||
}
|
||||
e->type = t;
|
||||
(*pinit) = new CommaExp(loc, e, (*pinit));
|
||||
|
||||
/* Replace __ctmp being constructed with e1
|
||||
/* Replace __ctmp being constructed with e1.
|
||||
* We need to copy constructor call expression,
|
||||
* because it may be used in other place.
|
||||
*/
|
||||
dve->e1 = e1;
|
||||
DotVarExp *dvx = (DotVarExp *)dve->copy();
|
||||
dvx->e1 = e1;
|
||||
CallExp *cx = (CallExp *)ce->copy();
|
||||
cx->e1 = dvx;
|
||||
|
||||
(*pinit) = new CommaExp(loc, e, cx);
|
||||
(*pinit) = (*pinit)->semantic(sc);
|
||||
goto Ldtor;
|
||||
}
|
||||
@@ -1466,7 +1524,7 @@ Lnomatch:
|
||||
}
|
||||
else
|
||||
{
|
||||
init = init->semantic(sc, type, WANTinterpret);
|
||||
init = init->semantic(sc, type, INITinterpret);
|
||||
}
|
||||
}
|
||||
else if (storage_class & (STCconst | STCimmutable | STCmanifest) ||
|
||||
@@ -1537,7 +1595,7 @@ Lnomatch:
|
||||
}
|
||||
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
|
||||
@@ -1552,7 +1610,7 @@ Lnomatch:
|
||||
else if (ei)
|
||||
{
|
||||
if (isDataseg() || (storage_class & STCmanifest))
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
else
|
||||
e = e->optimize(WANTvalue);
|
||||
switch (e->op)
|
||||
@@ -1639,7 +1697,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--;
|
||||
}
|
||||
sem = Semantic2Done;
|
||||
@@ -1710,9 +1768,8 @@ 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
|
||||
|
||||
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign,
|
||||
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment,
|
||||
&ad->structsize, &ad->alignsize, isunion);
|
||||
|
||||
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
|
||||
@@ -1831,28 +1888,8 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
|
||||
// The current function
|
||||
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
|
||||
|
||||
if (fdv && fdthis && fdv != fdthis && fdthis->ident != Id::ensure && fdthis->ident != Id::require)
|
||||
if (fdv && fdthis && fdv != fdthis)
|
||||
{
|
||||
/* __ensure is always called directly,
|
||||
* so it never becomes closure.
|
||||
*/
|
||||
|
||||
//printf("\tfdv = %s\n", fdv->toChars());
|
||||
//printf("\tfdthis = %s\n", fdthis->toChars());
|
||||
|
||||
if (loc.filename)
|
||||
fdthis->getLevel(loc, sc, fdv);
|
||||
|
||||
// Function literals from fdthis to fdv must be delegates
|
||||
for (Dsymbol *s = fdthis; s && s != fdv; s = s->toParent2())
|
||||
{
|
||||
// function literal has reference to enclosing scope is delegate
|
||||
if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
|
||||
{
|
||||
fld->tok = TOKdelegate;
|
||||
}
|
||||
}
|
||||
|
||||
// Add fdthis to nestedrefs[] if not already there
|
||||
for (size_t i = 0; 1; i++)
|
||||
{
|
||||
@@ -1865,23 +1902,46 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
|
||||
break;
|
||||
}
|
||||
|
||||
// Add this to fdv->closureVars[] if not already there
|
||||
for (size_t i = 0; 1; i++)
|
||||
if (fdthis->ident != Id::ensure)
|
||||
{
|
||||
if (i == fdv->closureVars.dim)
|
||||
{
|
||||
fdv->closureVars.push(this);
|
||||
break;
|
||||
}
|
||||
if (fdv->closureVars[i] == this)
|
||||
break;
|
||||
}
|
||||
/* __ensure is always called directly,
|
||||
* so it never becomes closure.
|
||||
*/
|
||||
|
||||
//printf("fdthis is %s\n", fdthis->toChars());
|
||||
//printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
|
||||
// __dollar creates problems because it isn't a real variable Bugzilla 3326
|
||||
if (ident == Id::dollar)
|
||||
::error(loc, "cannnot use $ inside a function literal");
|
||||
//printf("\tfdv = %s\n", fdv->toChars());
|
||||
//printf("\tfdthis = %s\n", fdthis->toChars());
|
||||
|
||||
if (loc.filename)
|
||||
fdthis->getLevel(loc, sc, fdv);
|
||||
|
||||
// Function literals from fdthis to fdv must be delegates
|
||||
for (Dsymbol *s = fdthis; s && s != fdv; s = s->toParent2())
|
||||
{
|
||||
// function literal has reference to enclosing scope is delegate
|
||||
if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
|
||||
{
|
||||
fld->tok = TOKdelegate;
|
||||
}
|
||||
}
|
||||
|
||||
// Add this to fdv->closureVars[] if not already there
|
||||
for (size_t i = 0; 1; i++)
|
||||
{
|
||||
if (i == fdv->closureVars.dim)
|
||||
{
|
||||
fdv->closureVars.push(this);
|
||||
break;
|
||||
}
|
||||
if (fdv->closureVars[i] == this)
|
||||
break;
|
||||
}
|
||||
|
||||
//printf("fdthis is %s\n", fdthis->toChars());
|
||||
//printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
|
||||
// __dollar creates problems because it isn't a real variable Bugzilla 3326
|
||||
if (ident == Id::dollar)
|
||||
::error(loc, "cannnot use $ inside a function literal");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2353,7 +2413,7 @@ TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *t
|
||||
TypeInfoVectorDeclaration::TypeInfoVectorDeclaration(Type *tinfo)
|
||||
: TypeInfoDeclaration(tinfo, 0)
|
||||
{
|
||||
if (!Type::typeinfoarray)
|
||||
if (!Type::typeinfovector)
|
||||
{
|
||||
ObjectNotFound(Id::TypeInfo_Vector);
|
||||
}
|
||||
|
||||
+16
-4
@@ -101,6 +101,12 @@ enum PURE;
|
||||
#define STCdisable 0x2000000000LL // for functions that are not callable
|
||||
#define STCresult 0x4000000000LL // for result variables passed to out contracts
|
||||
#define STCnodefaultctor 0x8000000000LL // must be set inside constructor
|
||||
#define STCtemp 0x10000000000LL // temporary variable introduced by inlining
|
||||
// and used only in backend process, so it's rvalue
|
||||
|
||||
#ifdef BUG6652
|
||||
#define STCbug6652 0x800000000000LL //
|
||||
#endif
|
||||
|
||||
struct Match
|
||||
{
|
||||
@@ -136,7 +142,7 @@ struct Declaration : Dsymbol
|
||||
enum LINK linkage;
|
||||
int inuse; // used to detect cycles
|
||||
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
Expressions *attributes; // GCC decl/type attributes
|
||||
#endif
|
||||
|
||||
@@ -148,6 +154,8 @@ struct Declaration : Dsymbol
|
||||
unsigned size(Loc loc);
|
||||
void checkModify(Loc loc, Scope *sc, Type *t);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toJsonBuffer(OutBuffer *buf);
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
@@ -288,7 +296,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
|
||||
@@ -710,7 +718,7 @@ enum BUILTIN
|
||||
BUILTINbsr, // core.bitop.bsr
|
||||
BUILTINbsf, // core.bitop.bsf
|
||||
BUILTINbswap, // core.bitop.bswap
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
BUILTINgcc, // GCC builtin
|
||||
#endif
|
||||
};
|
||||
@@ -738,12 +746,14 @@ 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
|
||||
VarDeclaration *vthis; // 'this' parameter (member and nested)
|
||||
VarDeclaration *v_arguments; // '_arguments' parameter
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
VarDeclaration *v_arguments_var; // '_arguments' variable
|
||||
VarDeclaration *v_argptr; // '_argptr' variable
|
||||
#endif
|
||||
VarDeclaration *v_argsave; // save area for args passed in registers for variadic functions
|
||||
@@ -861,6 +871,7 @@ struct FuncDeclaration : Declaration
|
||||
void checkNestedReference(Scope *sc, Loc loc);
|
||||
int needsClosure();
|
||||
int hasNestedFrameRefs();
|
||||
void buildResultVar();
|
||||
Statement *mergeFrequire(Statement *, Expressions *params = 0);
|
||||
Statement *mergeFensure(Statement *, Expressions *params = 0);
|
||||
Parameters *getParameters(int *pvarargs);
|
||||
@@ -941,6 +952,7 @@ struct FuncAliasDeclaration : FuncDeclaration
|
||||
struct FuncLiteralDeclaration : FuncDeclaration
|
||||
{
|
||||
enum TOK tok; // TOKfunction or TOKdelegate
|
||||
Type *treq; // target of return type inference
|
||||
|
||||
FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
|
||||
ForeachStatement *fes);
|
||||
|
||||
+87
-25
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Version="9.00"
|
||||
Name="dmd_msc"
|
||||
ProjectGUID="{BAE0389D-7D3F-4D5E-AE0E-C871776E8432}"
|
||||
RootNamespace="dmd"
|
||||
@@ -768,6 +768,38 @@
|
||||
<File
|
||||
RelativePath=".\unialpha.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\unittests.c"
|
||||
@@ -1301,16 +1333,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\root\dchar.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\root\dchar.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\root\dmgcmem.c"
|
||||
>
|
||||
RelativePath=".\root\dmgcmem.c" >
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
@@ -1361,16 +1384,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\root\lstring.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\root\lstring.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\root\man.c"
|
||||
>
|
||||
RelativePath=".\root\man.c" >
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\root\port.c"
|
||||
@@ -1422,6 +1436,14 @@
|
||||
<File
|
||||
RelativePath=".\root\gc\bits.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
ExcludedFromBuild="true"
|
||||
@@ -1430,6 +1452,14 @@
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
ExcludedFromBuild="true"
|
||||
@@ -1446,6 +1476,14 @@
|
||||
<File
|
||||
RelativePath=".\root\gc\gc.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
ExcludedFromBuild="true"
|
||||
@@ -1454,6 +1492,14 @@
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
ExcludedFromBuild="true"
|
||||
@@ -1518,6 +1564,14 @@
|
||||
<File
|
||||
RelativePath=".\root\gc\win32.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
ExcludedFromBuild="true"
|
||||
@@ -1526,6 +1580,14 @@
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
ExcludedFromBuild="true"
|
||||
@@ -1645,7 +1707,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Building and running $(IntDir)\$(InputName).exe"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo$(IntDir)\$(InputName).obj /Fe$(IntDir)\$(InputName).exe $(InputPath)
if errorlevel 1 goto VCReportError
$(IntDir)\$(InputName).exe
"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo"$(IntDir)\$(InputName).obj" /Fe"$(IntDir)\$(InputName).exe" "$(InputPath)"
if errorlevel 1 goto VCReportError
"$(IntDir)\$(InputName).exe"
"
|
||||
AdditionalDependencies="cc.h;oper.h"
|
||||
Outputs="optab.c;debtab.c;cdxxx.c;elxxx.c;tytab.c;fltables.c"
|
||||
/>
|
||||
@@ -1656,7 +1718,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Building and running $(IntDir)\$(InputName).exe"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo$(IntDir)\$(InputName).obj /Fe$(IntDir)\$(InputName).exe $(InputPath)
if errorlevel 1 goto VCReportError
$(IntDir)\$(InputName).exe
"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo"$(IntDir)\$(InputName).obj" /Fe"$(IntDir)\$(InputName).exe" "$(InputPath)"
if errorlevel 1 goto VCReportError
"$(IntDir)\$(InputName).exe"
"
|
||||
AdditionalDependencies="cc.h;oper.h"
|
||||
Outputs="optab.c;debtab.c;cdxxx.c;elxxx.c;tytab.c;fltables.c"
|
||||
/>
|
||||
@@ -1667,7 +1729,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Building and running $(IntDir)\$(InputName).exe"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo$(IntDir)\$(InputName).obj /Fe$(IntDir)\$(InputName).exe $(InputPath)
if errorlevel 1 goto VCReportError
$(IntDir)\$(InputName).exe
"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo"$(IntDir)\$(InputName).obj" /Fe"$(IntDir)\$(InputName).exe" "$(InputPath)"
if errorlevel 1 goto VCReportError
"$(IntDir)\$(InputName).exe""
|
||||
AdditionalDependencies="cc.h;oper.h"
|
||||
Outputs="optab.c;debtab.c;cdxxx.c;elxxx.c;tytab.c;fltables.c"
|
||||
/>
|
||||
@@ -1678,7 +1740,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="Building and running $(IntDir)\$(InputName).exe"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo$(IntDir)\$(InputName).obj /Fe$(IntDir)\$(InputName).exe $(InputPath)
if errorlevel 1 goto VCReportError
$(IntDir)\$(InputName).exe
"
|
||||
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo"$(IntDir)\$(InputName).obj" /Fe"$(IntDir)\$(InputName).exe" "$(InputPath)"
if errorlevel 1 goto VCReportError
"$(IntDir)\$(InputName).exe"
"
|
||||
AdditionalDependencies="cc.h;oper.h"
|
||||
Outputs="optab.c;debtab.c;cdxxx.c;elxxx.c;tytab.c;fltables.c"
|
||||
/>
|
||||
|
||||
+9
-8
@@ -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;
|
||||
|
||||
+7
-34
@@ -624,7 +624,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);
|
||||
}
|
||||
|
||||
@@ -632,41 +632,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())
|
||||
@@ -903,7 +872,8 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
s = s2;
|
||||
else if (s2 && s != s2)
|
||||
{
|
||||
if (s->toAlias() == s2->toAlias())
|
||||
if (s->toAlias() == s2->toAlias() ||
|
||||
s->getType() == s2->getType() && s->getType())
|
||||
{
|
||||
/* After following aliases, we found the same
|
||||
* symbol, so it's not an ambiguity. But if one
|
||||
@@ -1175,6 +1145,8 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg
|
||||
result = foreach(sc, tm->members, dg, ctx, &n);
|
||||
else if (s->isTemplateInstance())
|
||||
;
|
||||
else if (s->isUnitTestDeclaration())
|
||||
;
|
||||
else
|
||||
result = dg(ctx, n++, s);
|
||||
|
||||
@@ -1423,6 +1395,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;
|
||||
}
|
||||
|
||||
+1
-2
@@ -90,7 +90,7 @@ struct TypeInfoDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
union tree_node;
|
||||
typedef union tree_node TYPE;
|
||||
#else
|
||||
@@ -158,7 +158,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 *getAccessModule();
|
||||
|
||||
+2
-2
@@ -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
|
||||
@@ -36,7 +36,7 @@ void dumpExpressions(int i, Expressions *exps)
|
||||
if (exps)
|
||||
{
|
||||
for (size_t j = 0; j < exps->dim; j++)
|
||||
{ Expression *e = exps->tdata()[j];
|
||||
{ Expression *e = (*exps)[j];
|
||||
indent(i);
|
||||
printf("(\n");
|
||||
e->dump(i + 2);
|
||||
|
||||
+10
-10
@@ -185,11 +185,11 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
assert(e->dyncast() == DYNCAST_EXPRESSION);
|
||||
e = e->semantic(sce);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
if (memtype)
|
||||
{
|
||||
e = e->implicitCastTo(sce, memtype);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
if (!isAnonymous())
|
||||
e = e->castTo(sce, type);
|
||||
t = memtype;
|
||||
@@ -197,7 +197,7 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
else if (em->type)
|
||||
{
|
||||
e = e->implicitCastTo(sce, em->type);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
assert(isAnonymous());
|
||||
t = e->type;
|
||||
}
|
||||
@@ -214,7 +214,7 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
t = Type::tint32;
|
||||
e = new IntegerExp(em->loc, 0, Type::tint32);
|
||||
e = e->implicitCastTo(sce, t);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
if (!isAnonymous())
|
||||
e = e->castTo(sce, type);
|
||||
}
|
||||
@@ -225,7 +225,7 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
emax = t->getProperty(0, Id::max);
|
||||
emax = emax->semantic(sce);
|
||||
emax = emax->optimize(WANTvalue | WANTinterpret);
|
||||
emax = emax->ctfeInterpret();
|
||||
}
|
||||
|
||||
// Set value to (elast + 1).
|
||||
@@ -233,7 +233,7 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
assert(elast);
|
||||
e = new EqualExp(TOKequal, em->loc, elast, emax);
|
||||
e = e->semantic(sce);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
if (e->toInteger())
|
||||
error("overflow of enum value %s", elast->toChars());
|
||||
|
||||
@@ -241,14 +241,14 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
|
||||
e = e->semantic(sce);
|
||||
e = e->castTo(sce, elast->type);
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
|
||||
if (t->isfloating())
|
||||
{
|
||||
// Check that e != elast (not always true for floats)
|
||||
Expression *etest = new EqualExp(TOKequal, em->loc, e, elast);
|
||||
etest = etest->semantic(sce);
|
||||
etest = etest->optimize(WANTvalue | WANTinterpret);
|
||||
etest = etest->ctfeInterpret();
|
||||
if (etest->toInteger())
|
||||
error("enum member %s has inexact value, due to loss of precision", em->toChars());
|
||||
}
|
||||
@@ -298,13 +298,13 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
// Compute if(e < minval)
|
||||
ec = new CmpExp(TOKlt, em->loc, e, minval);
|
||||
ec = ec->semantic(sce);
|
||||
ec = ec->optimize(WANTvalue | WANTinterpret);
|
||||
ec = ec->ctfeInterpret();
|
||||
if (ec->toInteger())
|
||||
minval = e;
|
||||
|
||||
ec = new CmpExp(TOKgt, em->loc, e, maxval);
|
||||
ec = ec->semantic(sce);
|
||||
ec = ec->optimize(WANTvalue | WANTinterpret);
|
||||
ec = ec->ctfeInterpret();
|
||||
if (ec->toInteger())
|
||||
maxval = e;
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ struct EnumDeclaration : ScopeDsymbol
|
||||
int isdeprecated;
|
||||
int isdone; // 0: not done
|
||||
// 1: semantic() successfully completed
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
Expressions *attributes; // GCC decl/type attributes
|
||||
#endif
|
||||
|
||||
|
||||
+530
-350
File diff suppressed because it is too large
Load Diff
+15
-5
@@ -18,6 +18,7 @@
|
||||
#include "intrange.h"
|
||||
|
||||
struct Type;
|
||||
struct TypeVector;
|
||||
struct Scope;
|
||||
struct TupleDeclaration;
|
||||
struct VarDeclaration;
|
||||
@@ -183,6 +184,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();
|
||||
@@ -432,7 +438,6 @@ struct StringExp : Expression
|
||||
StringExp(Loc loc, void *s, size_t len, unsigned char postfix);
|
||||
//Expression *syntaxCopy();
|
||||
int equals(Object *o);
|
||||
char *toChars();
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
size_t length();
|
||||
@@ -793,7 +798,6 @@ struct FuncExp : Expression
|
||||
FuncLiteralDeclaration *fd;
|
||||
TemplateDeclaration *td;
|
||||
enum TOK tok;
|
||||
Type *treq;
|
||||
|
||||
FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL);
|
||||
Expression *syntaxCopy();
|
||||
@@ -947,10 +951,11 @@ 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 *arrayOp(Scope *sc);
|
||||
Expression *interpretFourPointerRelation(InterState *istate, CtfeGoal goal);
|
||||
virtual Expression *arrayOp(Scope *sc);
|
||||
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
Expression *inlineScan(InlineScanState *iss);
|
||||
@@ -971,6 +976,7 @@ struct BinAssignExp : BinExp
|
||||
}
|
||||
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *arrayOp(Scope *sc);
|
||||
|
||||
Expression *op_overload(Scope *sc);
|
||||
|
||||
@@ -1330,7 +1336,7 @@ struct CastExp : UnaExp
|
||||
|
||||
struct VectorExp : UnaExp
|
||||
{
|
||||
Type *to;
|
||||
TypeVector *to; // the target vector type before semantic()
|
||||
unsigned dim; // number of elements in the vector
|
||||
|
||||
VectorExp(Loc loc, Expression *e, Type *t);
|
||||
@@ -1339,6 +1345,7 @@ struct VectorExp : UnaExp
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
dt_t **toDt(dt_t **pdt);
|
||||
#endif
|
||||
#if IN_LLVM
|
||||
DValue* toElem(IRState* irs);
|
||||
@@ -2154,5 +2161,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 */
|
||||
|
||||
+309
-280
@@ -51,13 +51,15 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
|
||||
outId = NULL;
|
||||
vresult = NULL;
|
||||
returnLabel = NULL;
|
||||
scout = NULL;
|
||||
fensure = NULL;
|
||||
fbody = NULL;
|
||||
localsymtab = NULL;
|
||||
vthis = NULL;
|
||||
v_arguments = NULL;
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
v_argptr = NULL;
|
||||
v_arguments_var = NULL;
|
||||
#endif
|
||||
v_argsave = NULL;
|
||||
parameters = NULL;
|
||||
@@ -223,11 +225,9 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
|
||||
if (isCtorDeclaration())
|
||||
sc->flags |= SCOPEctor;
|
||||
type = type->semantic(loc, sc);
|
||||
sc = sc->pop();
|
||||
|
||||
/* Apply const, immutable and shared storage class
|
||||
* to the function type
|
||||
/* Apply const, immutable, wild and shared storage class
|
||||
* to the function type. Do this before type semantic.
|
||||
*/
|
||||
StorageClass stc = storage_class;
|
||||
if (type->isImmutable())
|
||||
@@ -250,35 +250,28 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
case STCimmutable | STCshared | STCwild:
|
||||
// Don't use toInvariant(), as that will do a merge()
|
||||
type = type->makeInvariant();
|
||||
goto Lmerge;
|
||||
break;
|
||||
|
||||
case STCconst:
|
||||
case STCconst | STCwild:
|
||||
type = type->makeConst();
|
||||
goto Lmerge;
|
||||
break;
|
||||
|
||||
case STCshared | STCconst:
|
||||
case STCshared | STCconst | STCwild:
|
||||
type = type->makeSharedConst();
|
||||
goto Lmerge;
|
||||
break;
|
||||
|
||||
case STCshared:
|
||||
type = type->makeShared();
|
||||
goto Lmerge;
|
||||
break;
|
||||
|
||||
case STCwild:
|
||||
type = type->makeWild();
|
||||
goto Lmerge;
|
||||
break;
|
||||
|
||||
case STCshared | STCwild:
|
||||
type = type->makeSharedWild();
|
||||
goto Lmerge;
|
||||
|
||||
Lmerge:
|
||||
if (!(type->ty == Tfunction && !type->nextOf()))
|
||||
/* Can't do merge if return type is not known yet
|
||||
*/
|
||||
type->deco = type->merge()->deco;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
@@ -287,7 +280,11 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
type = type->semantic(loc, sc);
|
||||
sc = sc->pop();
|
||||
}
|
||||
|
||||
storage_class &= ~STCref;
|
||||
if (type->ty != Tfunction)
|
||||
{
|
||||
@@ -401,18 +398,6 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
if (!fbody && (fensure || frequire) && !(id && isVirtual()))
|
||||
error("in and out contracts require function body");
|
||||
|
||||
/* Template member functions aren't virtual:
|
||||
* interface TestInterface { void tpl(T)(); }
|
||||
* and so won't work in interfaces
|
||||
*/
|
||||
if ((pd = toParent()) != NULL &&
|
||||
pd->isTemplateInstance() &&
|
||||
(pd = toParent2()) != NULL &&
|
||||
(id = pd->isInterfaceDeclaration()) != NULL)
|
||||
{
|
||||
error("template member functions are not allowed in interface %s", id->toChars());
|
||||
}
|
||||
|
||||
cd = parent->isClassDeclaration();
|
||||
if (cd)
|
||||
{ int vi;
|
||||
@@ -550,9 +535,6 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
break;
|
||||
|
||||
else if (!this->parent->isClassDeclaration() // if both are mixins then error
|
||||
#if !BREAKABI
|
||||
&& !isDtorDeclaration()
|
||||
#endif
|
||||
#if DMDV2
|
||||
&& !isPostBlitDeclaration()
|
||||
#endif
|
||||
@@ -610,7 +592,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
return;
|
||||
|
||||
default:
|
||||
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi];
|
||||
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl[vi];
|
||||
Type *ti = NULL;
|
||||
|
||||
/* Remember which functions this overrides
|
||||
@@ -920,7 +902,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
{
|
||||
for (int i = 0; i < fthrows->dim; i++)
|
||||
{
|
||||
Type *t = fthrows->tdata()[i];
|
||||
Type *t = (*fthrows)[i];
|
||||
|
||||
t = t->semantic(loc, sc);
|
||||
if (!t->isClassHandle())
|
||||
@@ -929,11 +911,17 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
}
|
||||
#endif
|
||||
|
||||
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++)
|
||||
{
|
||||
FuncDeclaration *fdv = foverrides.tdata()[i];
|
||||
FuncDeclaration *fdv = foverrides[i];
|
||||
|
||||
if (fdv->fbody && !fdv->frequire)
|
||||
{
|
||||
@@ -971,7 +959,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;
|
||||
#if !IN_LLVM
|
||||
sc2->tf = NULL;
|
||||
@@ -992,9 +980,6 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
}
|
||||
else
|
||||
assert(!isNested() || sc->intypeof); // can't be both member and nested
|
||||
#if IN_GCC
|
||||
ad->methods.push(this);
|
||||
#endif
|
||||
}
|
||||
vthis = declareThis(sc2, ad);
|
||||
|
||||
@@ -1028,7 +1013,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;
|
||||
v_arguments->semantic(sc2);
|
||||
@@ -1041,18 +1025,10 @@ 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
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
t = d_gcc_builtin_va_list_d_type;
|
||||
#else
|
||||
t = Type::tvoid->pointerTo();
|
||||
@@ -1094,7 +1070,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (f->parameters)
|
||||
{
|
||||
for (size_t i = 0; i < f->parameters->dim; i++)
|
||||
{ Parameter *arg = f->parameters->tdata()[i];
|
||||
{ Parameter *arg = (*f->parameters)[i];
|
||||
|
||||
//printf("[%d] arg->type->ty = %d %s\n", i, arg->type->ty, arg->type->toChars());
|
||||
if (arg->type->ty == Ttuple)
|
||||
@@ -1158,7 +1134,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (f->parameters)
|
||||
{
|
||||
for (size_t i = 0; i < f->parameters->dim; i++)
|
||||
{ Parameter *arg = f->parameters->tdata()[i];
|
||||
{ Parameter *arg = (*f->parameters)[i];
|
||||
|
||||
if (!arg->ident)
|
||||
continue; // never used, so ignore
|
||||
@@ -1173,7 +1149,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->tdata()[j] = e;
|
||||
(*exps)[j] = e;
|
||||
}
|
||||
assert(arg->ident);
|
||||
TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps);
|
||||
@@ -1187,151 +1163,120 @@ 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
|
||||
#if IN_LLVM
|
||||
// We actually need a valid 'var' for codegen.
|
||||
ThisExp* tv = new ThisExp(0);
|
||||
tv->var = vthis;
|
||||
Expression *v = tv;
|
||||
#else
|
||||
Expression *v = new ThisExp(0);
|
||||
#endif
|
||||
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
|
||||
#if IN_LLVM
|
||||
// We actually need a valid 'var' for codegen.
|
||||
ThisExp* tv = new ThisExp(0);
|
||||
tv->var = vthis;
|
||||
Expression *v = tv;
|
||||
#else
|
||||
Expression *v = new ThisExp(0);
|
||||
#endif
|
||||
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()) // if return type is inferred
|
||||
{ /* This case:
|
||||
* auto fp = function() out { } body { };
|
||||
* Can fix by doing semantic() onf 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
|
||||
Loc loc = this->loc;
|
||||
|
||||
if (fensure)
|
||||
loc = fensure->loc;
|
||||
|
||||
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 (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
|
||||
ThisExp *tv = new ThisExp(0);
|
||||
tv->type = vthis->type;
|
||||
tv->var = vthis;
|
||||
Expression* v = tv;
|
||||
|
||||
#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)
|
||||
{ AggregateDeclaration *ad = isAggregateMember();
|
||||
AggregateDeclaration *ad = isAggregateMember();
|
||||
|
||||
/* If this is a class constructor
|
||||
*/
|
||||
@@ -1375,7 +1320,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < pd->members->dim; i++)
|
||||
{ Dsymbol *s = pd->members->tdata()[i];
|
||||
{ Dsymbol *s = (*pd->members)[i];
|
||||
|
||||
s->checkCtorConstInit();
|
||||
}
|
||||
@@ -1460,15 +1405,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;
|
||||
@@ -1497,6 +1434,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;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1506,7 +1503,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (parameters)
|
||||
{ for (size_t i = 0; i < parameters->dim; i++)
|
||||
{
|
||||
VarDeclaration *v = parameters->tdata()[i];
|
||||
VarDeclaration *v = (*parameters)[i];
|
||||
if (v->storage_class & STCout)
|
||||
{
|
||||
assert(v->init);
|
||||
@@ -1548,7 +1545,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (parameters && parameters->dim)
|
||||
{
|
||||
int lastNonref = parameters->dim -1;
|
||||
p = parameters->tdata()[lastNonref];
|
||||
p = (*parameters)[lastNonref];
|
||||
/* The trouble with out and ref parameters is that taking
|
||||
* the address of it doesn't work, because later processing
|
||||
* adds in an extra level of indirection. So we skip over them.
|
||||
@@ -1562,7 +1559,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
p = v_arguments;
|
||||
break;
|
||||
}
|
||||
p = parameters->tdata()[lastNonref];
|
||||
p = (*parameters)[lastNonref];
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1586,6 +1583,10 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
|
||||
if (_arguments)
|
||||
{
|
||||
#ifdef IN_GCC
|
||||
v_arguments_var = _arguments;
|
||||
v_arguments_var->init = new VoidInitializer(loc);
|
||||
#endif
|
||||
/* Advance to elements[] member of TypeInfo_Tuple with:
|
||||
* _arguments = v_arguments.elements;
|
||||
*/
|
||||
@@ -1601,74 +1602,32 @@ 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
|
||||
ThisExp* tv = new ThisExp(0);
|
||||
tv->type = vthis->type;
|
||||
tv->var = vthis;
|
||||
Expression *v = tv;
|
||||
|
||||
#if STRUCTTHISREF
|
||||
if (ad->isStructDeclaration())
|
||||
v = v->addressOf(sc);
|
||||
#endif
|
||||
Expression *se = new StringExp(0, (char *)"null this");
|
||||
se = se->semantic(sc);
|
||||
#if !IN_LLVM
|
||||
se->type = Type::tchar->arrayOf();
|
||||
#endif
|
||||
e = new AssertExp(loc, v, 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)
|
||||
{
|
||||
#if IN_LLVM
|
||||
Expression *e = 0;
|
||||
@@ -1682,7 +1641,6 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
}
|
||||
#else
|
||||
// Create: return vresult;
|
||||
assert(vresult);
|
||||
Expression *e = new VarExp(0, vresult);
|
||||
#endif
|
||||
if (tintro)
|
||||
@@ -1693,6 +1651,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);
|
||||
|
||||
@@ -1740,17 +1703,19 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (parameters)
|
||||
{ for (size_t i = 0; i < parameters->dim; i++)
|
||||
{
|
||||
VarDeclaration *v = parameters->tdata()[i];
|
||||
VarDeclaration *v = (*parameters)[i];
|
||||
|
||||
if (v->storage_class & (STCref | STCout))
|
||||
if (v->storage_class & (STCref | STCout | STClazy))
|
||||
continue;
|
||||
|
||||
#if !SARRAYVALUE
|
||||
/* Don't do this for static arrays, since static
|
||||
* arrays are called by reference. Remove this
|
||||
* when we change them to call by value.
|
||||
*/
|
||||
if (v->type->toBasetype()->ty == Tsarray)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (v->noscope)
|
||||
continue;
|
||||
@@ -1987,6 +1952,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.
|
||||
@@ -2031,7 +2038,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf, Expressions *params)
|
||||
*/
|
||||
for (int i = 0; i < foverrides.dim; i++)
|
||||
{
|
||||
FuncDeclaration *fdv = foverrides.tdata()[i];
|
||||
FuncDeclaration *fdv = foverrides[i];
|
||||
|
||||
/* The semantic pass on the contracts of the overridden functions must
|
||||
* be completed before code generation occurs (bug 3602).
|
||||
@@ -2089,7 +2096,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Expressions *params)
|
||||
*/
|
||||
for (int i = 0; i < foverrides.dim; i++)
|
||||
{
|
||||
FuncDeclaration *fdv = foverrides.tdata()[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).
|
||||
@@ -2158,14 +2165,28 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
|
||||
FuncDeclaration *mismatch = NULL;
|
||||
StorageClass mismatchstc = 0;
|
||||
int mismatchvi = -1;
|
||||
int exactvi = -1;
|
||||
int bestvi = -1;
|
||||
for (int vi = 0; vi < dim; vi++)
|
||||
{
|
||||
FuncDeclaration *fdv = vtbl->tdata()[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;
|
||||
}
|
||||
|
||||
StorageClass stc = 0;
|
||||
int cov = type->covariant(fdv->type, &stc);
|
||||
@@ -2527,7 +2548,7 @@ if (arguments)
|
||||
for (i = 0; i < arguments->dim; i++)
|
||||
{ Expression *arg;
|
||||
|
||||
arg = arguments->tdata()[i];
|
||||
arg = (*arguments)[i];
|
||||
assert(arg->type);
|
||||
printf("\t%s: ", arg->toChars());
|
||||
arg->type->print();
|
||||
@@ -2570,7 +2591,7 @@ if (arguments)
|
||||
OutBuffer buf2;
|
||||
tf->modToBuffer(&buf2);
|
||||
|
||||
//printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco);
|
||||
//printf("tf = %s, args = %s\n", tf->deco, (*arguments)[0]->type->deco);
|
||||
error(loc, "%s%s is not callable using argument types %s",
|
||||
Parameter::argsTypesToChars(tf->parameters, tf->varargs),
|
||||
buf2.toChars(),
|
||||
@@ -2656,7 +2677,7 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
|
||||
}
|
||||
else
|
||||
e = p->type->defaultInitLiteral(0);
|
||||
args.tdata()[u] = e;
|
||||
args[u] = e;
|
||||
}
|
||||
|
||||
MATCH m = (MATCH) tg->callMatch(NULL, &args, 1);
|
||||
@@ -2797,14 +2818,25 @@ int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
|
||||
//printf("\ts = %s, '%s'\n", s->kind(), s->toChars());
|
||||
FuncDeclaration *thisfd = s->isFuncDeclaration();
|
||||
if (thisfd)
|
||||
{ if (!thisfd->isNested() && !thisfd->vthis)
|
||||
{ if (!thisfd->isNested() && !thisfd->vthis && !sc->intypeof)
|
||||
goto Lerr;
|
||||
}
|
||||
else
|
||||
{
|
||||
AggregateDeclaration *thiscd = s->isAggregateDeclaration();
|
||||
if (thiscd)
|
||||
{ if (!thiscd->isNested())
|
||||
{
|
||||
/* AggregateDeclaration::isNested returns true only when
|
||||
* it has a hidden pointer.
|
||||
* But, calling the function belongs unrelated lexical scope
|
||||
* is still allowed inside typeof.
|
||||
*
|
||||
* struct Map(alias fun) {
|
||||
* typeof({ return fun(); }) RetType;
|
||||
* // No member function makes Map struct 'not nested'.
|
||||
* }
|
||||
*/
|
||||
if (!thiscd->isNested() && !sc->intypeof)
|
||||
goto Lerr;
|
||||
}
|
||||
else
|
||||
@@ -3081,6 +3113,7 @@ int FuncDeclaration::isNested()
|
||||
FuncDeclaration *f = toAliasFunc();
|
||||
//printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars());
|
||||
return ((f->storage_class & STCstatic) == 0) &&
|
||||
(f->linkage == LINKd) &&
|
||||
(f->toParent2()->isFuncDeclaration() != NULL);
|
||||
}
|
||||
|
||||
@@ -3222,12 +3255,12 @@ int FuncDeclaration::needsClosure()
|
||||
|
||||
//printf("FuncDeclaration::needsClosure() %s\n", toChars());
|
||||
for (int i = 0; i < closureVars.dim; i++)
|
||||
{ VarDeclaration *v = closureVars.tdata()[i];
|
||||
{ VarDeclaration *v = closureVars[i];
|
||||
assert(v->isVarDeclaration());
|
||||
//printf("\tv = %s\n", v->toChars());
|
||||
|
||||
for (int j = 0; j < v->nestedrefs.dim; j++)
|
||||
{ FuncDeclaration *f = v->nestedrefs.tdata()[j];
|
||||
{ FuncDeclaration *f = v->nestedrefs[j];
|
||||
assert(f != this);
|
||||
|
||||
//printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
|
||||
@@ -3298,7 +3331,7 @@ int FuncDeclaration::hasNestedFrameRefs()
|
||||
{
|
||||
for (size_t i = 0; i < foverrides.dim; i++)
|
||||
{
|
||||
FuncDeclaration *fdv = foverrides.tdata()[i];
|
||||
FuncDeclaration *fdv = foverrides[i];
|
||||
if (fdv->hasNestedFrameRefs())
|
||||
return 1;
|
||||
}
|
||||
@@ -3386,6 +3419,7 @@ FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
|
||||
this->ident = Lexer::uniqueId(id);
|
||||
this->tok = tok;
|
||||
this->fes = fes;
|
||||
this->treq = NULL;
|
||||
//printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
|
||||
}
|
||||
|
||||
@@ -3399,6 +3433,7 @@ Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
|
||||
else
|
||||
{ f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes);
|
||||
f->ident = ident; // keep old identifier
|
||||
f->treq = treq; // don't need to copy
|
||||
}
|
||||
FuncDeclaration::syntaxCopy(f);
|
||||
return f;
|
||||
@@ -3713,14 +3748,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
-1
@@ -84,7 +84,7 @@ void Module::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = members->tdata()[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
|
||||
s->toHBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -66,6 +66,7 @@ Msgtable msgtable[] =
|
||||
{ "outer" },
|
||||
{ "Exception" },
|
||||
{ "AssociativeArray" },
|
||||
{ "RTInfo" },
|
||||
{ "Throwable" },
|
||||
{ "Error" },
|
||||
{ "withSym", "__withSym" },
|
||||
@@ -356,6 +357,7 @@ Msgtable msgtable[] =
|
||||
{ "derivedMembers" },
|
||||
{ "isSame" },
|
||||
{ "compiles" },
|
||||
{ "parameters" },
|
||||
};
|
||||
|
||||
|
||||
|
||||
+35
-7
@@ -45,7 +45,7 @@ Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *alias
|
||||
this->ident = aliasId;
|
||||
// import [std].stdio;
|
||||
else if (packages && packages->dim)
|
||||
this->ident = packages->tdata()[0];
|
||||
this->ident = (*packages)[0];
|
||||
// import [foo];
|
||||
else
|
||||
this->ident = id;
|
||||
@@ -112,8 +112,18 @@ void Import::load(Scope *sc)
|
||||
if (s->isModule())
|
||||
mod = (Module *)s;
|
||||
else
|
||||
::error(loc, "can only import from a module, not from package %s.%s",
|
||||
pkg->toPrettyChars(), id->toChars());
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
@@ -356,8 +366,8 @@ int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
*/
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
Identifier *name = names.tdata()[i];
|
||||
Identifier *alias = aliases.tdata()[i];
|
||||
Identifier *name = names[i];
|
||||
Identifier *alias = aliases[i];
|
||||
|
||||
if (!alias)
|
||||
alias = name;
|
||||
@@ -413,12 +423,30 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = packages->tdata()[i];
|
||||
{ Identifier *pid = (*packages)[i];
|
||||
|
||||
buf->printf("%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
buf->printf("%s;", id->toChars());
|
||||
buf->printf("%s", id->toChars());
|
||||
if (names.dim)
|
||||
{
|
||||
buf->writestring(" : ");
|
||||
for (size_t i = 0; i < names.dim; i++)
|
||||
{
|
||||
Identifier *name = names[i];
|
||||
Identifier *alias = aliases[i];
|
||||
|
||||
if (alias)
|
||||
buf->printf("%s = %s", alias->toChars(), name->toChars());
|
||||
else
|
||||
buf->printf("%s", name->toChars());
|
||||
|
||||
if (i < names.dim - 1)
|
||||
buf->writestring(", ");
|
||||
}
|
||||
}
|
||||
buf->printf(";");
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Some portions copyright (c) 1994-1995 by Symantec
|
||||
* Copyright (c) 1999-2011 by Digital Mars
|
||||
* Copyright (c) 1999-2012 by Digital Mars
|
||||
* All Rights Reserved
|
||||
* http://www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
@@ -31,6 +31,10 @@
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
|
||||
#include "gnuc.h"
|
||||
#endif
|
||||
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
|
||||
+64
-13
@@ -35,7 +35,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;
|
||||
}
|
||||
@@ -88,7 +88,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;
|
||||
@@ -145,7 +145,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;
|
||||
|
||||
@@ -227,7 +227,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
}
|
||||
if (s && (v = s->isVarDeclaration()) != NULL)
|
||||
{
|
||||
val = val->semantic(sc, v->type, needInterpret);
|
||||
val = val->semantic(sc, v->type->addMod(t->mod), needInterpret);
|
||||
value[i] = val;
|
||||
vars[i] = v;
|
||||
}
|
||||
@@ -353,8 +353,12 @@ Expression *StructInitializer::toExpression()
|
||||
else
|
||||
{
|
||||
if (!(*elements)[i])
|
||||
// Default initialize
|
||||
(*elements)[i] = vd->type->defaultInit();
|
||||
{ // Default initialize
|
||||
if (vd->init)
|
||||
(*elements)[i] = vd->init->toExpression();
|
||||
else
|
||||
(*elements)[i] = vd->type->defaultInit();
|
||||
}
|
||||
}
|
||||
offset = vd->offset + vd->type->size();
|
||||
i++;
|
||||
@@ -464,7 +468,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;
|
||||
@@ -482,6 +486,10 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
case Tarray:
|
||||
break;
|
||||
|
||||
case Tvector:
|
||||
t = ((TypeVector *)t)->basetype;
|
||||
break;
|
||||
|
||||
default:
|
||||
error(loc, "cannot use array to initialize %s", type->toChars());
|
||||
goto Lerr;
|
||||
@@ -493,14 +501,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");
|
||||
@@ -746,6 +779,7 @@ ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
|
||||
: Initializer(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
this->expandTuples = 0;
|
||||
}
|
||||
|
||||
Initializer *ExpInitializer::syntaxCopy()
|
||||
@@ -757,6 +791,9 @@ bool arrayHasNonConstPointers(Expressions *elems);
|
||||
|
||||
bool hasNonConstPointers(Expression *e)
|
||||
{
|
||||
if (e->type->ty == Terror)
|
||||
return false;
|
||||
|
||||
if (e->op == TOKnull)
|
||||
return false;
|
||||
if (e->op == TOKstructliteral)
|
||||
@@ -817,15 +854,19 @@ bool arrayHasNonConstPointers(Expressions *elems)
|
||||
|
||||
|
||||
|
||||
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);
|
||||
exp = resolveProperties(sc, exp);
|
||||
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
|
||||
|
||||
@@ -841,6 +882,11 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
||||
|
||||
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";
|
||||
@@ -870,8 +916,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;
|
||||
}
|
||||
|
||||
+8
-6
@@ -34,6 +34,7 @@ namespace llvm {
|
||||
}
|
||||
#endif
|
||||
|
||||
enum NeedInterpret { INITnointerpret, INITinterpret };
|
||||
|
||||
struct Initializer : Object
|
||||
{
|
||||
@@ -41,8 +42,8 @@ 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);
|
||||
// needInterpret is INITinterpret if must be a manifest constant, 0 if not.
|
||||
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 +67,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 +89,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 +114,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);
|
||||
int isAssociativeArray();
|
||||
Type *inferType(Scope *sc);
|
||||
Expression *toExpression();
|
||||
@@ -131,10 +132,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);
|
||||
|
||||
+78
-18
@@ -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
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h> // memset()
|
||||
|
||||
#include "id.h"
|
||||
#include "init.h"
|
||||
@@ -618,11 +619,11 @@ Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids)
|
||||
newa->setDim(a->dim);
|
||||
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{ Expression *e = a->tdata()[i];
|
||||
{ Expression *e = (*a)[i];
|
||||
|
||||
if (e)
|
||||
e = e->doInline(ids);
|
||||
newa->tdata()[i] = e;
|
||||
(*newa)[i] = e;
|
||||
}
|
||||
}
|
||||
return newa;
|
||||
@@ -639,11 +640,11 @@ Expression *SymOffExp::doInline(InlineDoState *ids)
|
||||
//printf("SymOffExp::doInline(%s)\n", toChars());
|
||||
for (size_t i = 0; i < ids->from.dim; i++)
|
||||
{
|
||||
if (var == ids->from.tdata()[i])
|
||||
if (var == ids->from[i])
|
||||
{
|
||||
SymOffExp *se = (SymOffExp *)copy();
|
||||
|
||||
se->var = (Declaration *)ids->to.tdata()[i];
|
||||
se->var = (Declaration *)ids->to[i];
|
||||
return se;
|
||||
}
|
||||
}
|
||||
@@ -655,11 +656,11 @@ Expression *VarExp::doInline(InlineDoState *ids)
|
||||
//printf("VarExp::doInline(%s)\n", toChars());
|
||||
for (size_t i = 0; i < ids->from.dim; i++)
|
||||
{
|
||||
if (var == ids->from.tdata()[i])
|
||||
if (var == ids->from[i])
|
||||
{
|
||||
VarExp *ve = (VarExp *)copy();
|
||||
|
||||
ve->var = (Declaration *)ids->to.tdata()[i];
|
||||
ve->var = (Declaration *)ids->to[i];
|
||||
return ve;
|
||||
}
|
||||
}
|
||||
@@ -709,7 +710,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
|
||||
if (td)
|
||||
{
|
||||
for (size_t i = 0; i < td->objects->dim; i++)
|
||||
{ DsymbolExp *se = td->objects->tdata()[i];
|
||||
{ DsymbolExp *se = (*td->objects)[i];
|
||||
assert(se->op == TOKdsymbol);
|
||||
se->s;
|
||||
}
|
||||
@@ -1098,8 +1099,8 @@ Statement *SwitchStatement::inlineScan(InlineScanState *iss)
|
||||
for (size_t i = 0; i < cases->dim; i++)
|
||||
{ CaseStatement *s;
|
||||
|
||||
s = cases->tdata()[i];
|
||||
cases->tdata()[i] = (CaseStatement *)s->inlineScan(iss);
|
||||
s = (*cases)[i];
|
||||
(*cases)[i] = (CaseStatement *)s->inlineScan(iss);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@@ -1130,6 +1131,65 @@ Statement *ReturnStatement::inlineScan(InlineScanState *iss)
|
||||
if (exp)
|
||||
{
|
||||
exp = exp->inlineScan(iss);
|
||||
|
||||
FuncDeclaration *func = iss->fd;
|
||||
TypeFunction *tf = (TypeFunction *)(func->type);
|
||||
|
||||
/* Postblit call on return statement is processed in glue layer
|
||||
* (Because NRVO may eliminate the copy), but inlining may remove
|
||||
* ReturnStatement itself. To keep semantics we should insert
|
||||
* temporary variable for postblit call.
|
||||
* This is mostly the same as ReturnStatement::toIR.
|
||||
*/
|
||||
enum RET retmethod = tf->retStyle();
|
||||
if (retmethod == RETstack)
|
||||
{
|
||||
if (func->nrvo_can && func->nrvo_var)
|
||||
;
|
||||
else
|
||||
{
|
||||
Type *tb = exp->type->toBasetype();
|
||||
if (exp->isLvalue() && tb->ty == Tstruct)
|
||||
{ StructDeclaration *sd = ((TypeStruct *)tb)->sym;
|
||||
if (sd->postblit)
|
||||
{ FuncDeclaration *fd = sd->postblit;
|
||||
if (fd->storage_class & STCdisable)
|
||||
{
|
||||
fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
|
||||
}
|
||||
|
||||
/* Rewirte exp as:
|
||||
* (__inlinectmp = exp), __inlinectmp.__postblit(), __inlinectmp
|
||||
* And, __inlinectmp is marked as rvalue (See STCtemp comment)
|
||||
*/
|
||||
ExpInitializer *ei = new ExpInitializer(loc, exp);
|
||||
|
||||
Identifier* tmp = Identifier::generateId("__inlinectmp");
|
||||
VarDeclaration *v = new VarDeclaration(loc, exp->type, tmp, ei);
|
||||
v->storage_class = STCtemp;
|
||||
v->linkage = LINKd;
|
||||
v->parent = func;
|
||||
|
||||
VarExp *ve = new VarExp(loc, v);
|
||||
ve->type = exp->type;
|
||||
|
||||
ei->exp = new ConstructExp(loc, ve, exp);
|
||||
ei->exp->type = exp->type;
|
||||
|
||||
DeclarationExp *de = new DeclarationExp(0, v);
|
||||
de->type = Type::tvoid;
|
||||
|
||||
Expression *e = new DotVarExp(ve->loc, ve, sd->postblit, 0);
|
||||
e->type = sd->postblit->type;
|
||||
e = new CallExp(ve->loc, e);
|
||||
e->type = Type::tvoid;
|
||||
|
||||
exp = Expression::combine(de, e);
|
||||
exp = Expression::combine(exp, ve);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -1162,7 +1222,7 @@ Statement *TryCatchStatement::inlineScan(InlineScanState *iss)
|
||||
if (catches)
|
||||
{
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
{ Catch *c = catches->tdata()[i];
|
||||
{ Catch *c = (*catches)[i];
|
||||
|
||||
if (c->handler)
|
||||
c->handler = c->handler->inlineScan(iss);
|
||||
@@ -1212,12 +1272,12 @@ void arrayInlineScan(InlineScanState *iss, Expressions *arguments)
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = arguments->tdata()[i];
|
||||
{ Expression *e = (*arguments)[i];
|
||||
|
||||
if (e)
|
||||
{
|
||||
e = e->inlineScan(iss);
|
||||
arguments->tdata()[i] = e;
|
||||
(*arguments)[i] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1237,7 +1297,7 @@ void scanVar(Dsymbol *s, InlineScanState *iss)
|
||||
if (td)
|
||||
{
|
||||
for (size_t i = 0; i < td->objects->dim; i++)
|
||||
{ DsymbolExp *se = (DsymbolExp *)td->objects->tdata()[i];
|
||||
{ DsymbolExp *se = (DsymbolExp *)(*td->objects)[i];
|
||||
assert(se->op == TOKdsymbol);
|
||||
scanVar(se->s, iss);
|
||||
}
|
||||
@@ -1546,7 +1606,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
|
||||
{
|
||||
for (size_t i = 0; i < parameters->dim; i++)
|
||||
{
|
||||
VarDeclaration *v = parameters->tdata()[i];
|
||||
VarDeclaration *v = (*parameters)[i];
|
||||
if (v->type->toBasetype()->ty == Tsarray)
|
||||
goto Lno;
|
||||
}
|
||||
@@ -1701,9 +1761,9 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
||||
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{
|
||||
VarDeclaration *vfrom = parameters->tdata()[i];
|
||||
VarDeclaration *vfrom = (*parameters)[i];
|
||||
VarDeclaration *vto;
|
||||
Expression *arg = arguments->tdata()[i];
|
||||
Expression *arg = (*arguments)[i];
|
||||
ExpInitializer *ei;
|
||||
VarExp *ve;
|
||||
|
||||
@@ -1778,7 +1838,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
||||
|
||||
Identifier* tmp = Identifier::generateId("__inlineretval");
|
||||
VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei);
|
||||
vd->storage_class = tf->isref ? STCref : 0;
|
||||
vd->storage_class = (tf->isref ? STCref : 0) | STCtemp;
|
||||
vd->linkage = tf->linkage;
|
||||
vd->parent = iss->fd;
|
||||
|
||||
|
||||
+585
-218
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -95,14 +95,14 @@ struct IntRange
|
||||
IntRange(const SignExtendedNumber& a)
|
||||
: imin(a), imax(a) {}
|
||||
/// Create a range with the lower and upper bounds.
|
||||
IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper)
|
||||
IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper)
|
||||
: imin(lower), imax(upper) {}
|
||||
|
||||
|
||||
/// Create the tightest range containing all valid integers in the specified
|
||||
/// type.
|
||||
/// type.
|
||||
static IntRange fromType(Type *type);
|
||||
/// Create the tightest range containing all valid integers in the type with
|
||||
/// a forced signedness.
|
||||
/// a forced signedness.
|
||||
static IntRange fromType(Type *type, bool isUnsigned);
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ struct IntRange
|
||||
/// Check if this range contains 0.
|
||||
bool containsZero() const;
|
||||
|
||||
/// Compute the range of the negated absolute values of the original range.
|
||||
/// Compute the range of the negated absolute values of the original range.
|
||||
IntRange absNeg() const;
|
||||
|
||||
/// Compute the union of two ranges.
|
||||
@@ -139,7 +139,7 @@ struct IntRange
|
||||
void unionOrAssign(const IntRange& other, bool& union_);
|
||||
|
||||
/// Dump the content of the integer range to the console.
|
||||
const IntRange& dump(const char* funcName, Expression *e) const;
|
||||
const IntRange& dump(const char* funcName, Expression *e) const;
|
||||
|
||||
/// Split the range into two nonnegative- and negative-only subintervals.
|
||||
void splitBySign(IntRange& negRange, bool& hasNegRange,
|
||||
|
||||
+9
-9
@@ -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
|
||||
@@ -53,7 +53,7 @@ void json_generate(Modules *modules)
|
||||
|
||||
buf.writestring("[\n");
|
||||
for (size_t i = 0; i < modules->dim; i++)
|
||||
{ Module *m = modules->tdata()[i];
|
||||
{ Module *m = (*modules)[i];
|
||||
if (global.params.verbose)
|
||||
printf("json gen %s\n", m->toChars());
|
||||
m->toJsonBuffer(&buf);
|
||||
@@ -66,7 +66,7 @@ void json_generate(Modules *modules)
|
||||
char *arg = global.params.xfilename;
|
||||
if (!arg || !*arg)
|
||||
{ // Generate lib file name from first obj name
|
||||
char *n = global.params.objfiles->tdata()[0];
|
||||
char *n = (*global.params.objfiles)[0];
|
||||
|
||||
n = FileName::name(n);
|
||||
FileName *fn = FileName::forceExt(n, global.json_ext);
|
||||
@@ -195,7 +195,7 @@ void Module::toJsonBuffer(OutBuffer *buf)
|
||||
|
||||
size_t offset = buf->offset;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = members->tdata()[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
if (offset != buf->offset)
|
||||
{ buf->writestring(",\n");
|
||||
offset = buf->offset;
|
||||
@@ -219,7 +219,7 @@ void AttribDeclaration::toJsonBuffer(OutBuffer *buf)
|
||||
{
|
||||
size_t offset = buf->offset;
|
||||
for (unsigned i = 0; i < d->dim; i++)
|
||||
{ Dsymbol *s = d->tdata()[i];
|
||||
{ Dsymbol *s = (*d)[i];
|
||||
//printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars());
|
||||
if (offset != buf->offset)
|
||||
{ buf->writestring(",\n");
|
||||
@@ -332,7 +332,7 @@ void AggregateDeclaration::toJsonBuffer(OutBuffer *buf)
|
||||
buf->writestring(" : [\n");
|
||||
size_t offset = buf->offset;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = members->tdata()[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
if (offset != buf->offset)
|
||||
{ buf->writestring(",\n");
|
||||
offset = buf->offset;
|
||||
@@ -369,7 +369,7 @@ void TemplateDeclaration::toJsonBuffer(OutBuffer *buf)
|
||||
buf->writestring(" : [\n");
|
||||
size_t offset = buf->offset;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = members->tdata()[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
if (offset != buf->offset)
|
||||
{ buf->writestring(",\n");
|
||||
offset = buf->offset;
|
||||
@@ -391,7 +391,7 @@ void EnumDeclaration::toJsonBuffer(OutBuffer *buf)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = members->tdata()[i];
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->toJsonBuffer(buf);
|
||||
buf->writestring(",\n");
|
||||
}
|
||||
@@ -423,7 +423,7 @@ void EnumDeclaration::toJsonBuffer(OutBuffer *buf)
|
||||
buf->writestring(" : [\n");
|
||||
size_t offset = buf->offset;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = members->tdata()[i];
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
if (offset != buf->offset)
|
||||
{ buf->writestring(",\n");
|
||||
offset = buf->offset;
|
||||
|
||||
+28
-171
@@ -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
|
||||
@@ -108,14 +108,22 @@ const char *Token::toChars()
|
||||
switch (value)
|
||||
{
|
||||
case TOKint32v:
|
||||
#if defined(IN_GCC) || defined(IN_LLVM)
|
||||
sprintf(buffer,"%d",(d_int32)int64value);
|
||||
#else
|
||||
sprintf(buffer,"%d",int32value);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TOKuns32v:
|
||||
case TOKcharv:
|
||||
case TOKwcharv:
|
||||
case TOKdcharv:
|
||||
#ifdef defined(IN_GCC) || defined(IN_LLVM)
|
||||
sprintf(buffer,"%uU",(d_uns32)uns64value);
|
||||
#else
|
||||
sprintf(buffer,"%uU",uns32value);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TOKint64v:
|
||||
@@ -126,7 +134,7 @@ const char *Token::toChars()
|
||||
sprintf(buffer,"%lluUL",(uintmax_t)uns64value);
|
||||
break;
|
||||
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
case TOKfloat32v:
|
||||
case TOKfloat64v:
|
||||
case TOKfloat80v:
|
||||
@@ -171,9 +179,6 @@ const char *Token::toChars()
|
||||
#endif
|
||||
|
||||
case TOKstring:
|
||||
#if CSTRINGS
|
||||
p = string;
|
||||
#else
|
||||
{ OutBuffer buf;
|
||||
|
||||
buf.writeByte('"');
|
||||
@@ -208,7 +213,6 @@ const char *Token::toChars()
|
||||
buf.writeByte(0);
|
||||
p = (char *)buf.extractData();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TOKidentifier:
|
||||
@@ -305,7 +309,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);
|
||||
}
|
||||
|
||||
@@ -313,34 +317,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;
|
||||
|
||||
@@ -524,30 +504,6 @@ void Lexer::scan(Token *t)
|
||||
t->value = number(t);
|
||||
return;
|
||||
|
||||
#if CSTRINGS
|
||||
case '\'':
|
||||
t->value = charConstant(t, 0);
|
||||
return;
|
||||
|
||||
case '"':
|
||||
t->value = stringConstant(t,0);
|
||||
return;
|
||||
|
||||
case 'l':
|
||||
case 'L':
|
||||
if (p[1] == '\'')
|
||||
{
|
||||
p++;
|
||||
t->value = charConstant(t, 1);
|
||||
return;
|
||||
}
|
||||
else if (p[1] == '"')
|
||||
{
|
||||
p++;
|
||||
t->value = stringConstant(t, 1);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
case '\'':
|
||||
t->value = charConstant(t,0);
|
||||
return;
|
||||
@@ -627,12 +583,9 @@ void Lexer::scan(Token *t)
|
||||
}
|
||||
#endif
|
||||
|
||||
case 'l':
|
||||
case 'L':
|
||||
#endif
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'm': case 'n': case 'o':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
#if DMDV2
|
||||
case 'p': /*case 'q': case 'r':*/ case 's': case 't':
|
||||
#else
|
||||
@@ -642,7 +595,7 @@ void Lexer::scan(Token *t)
|
||||
case 'z':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'M': case 'N': case 'O':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y':
|
||||
case 'Z':
|
||||
@@ -669,7 +622,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;
|
||||
@@ -1228,10 +1181,10 @@ void Lexer::scan(Token *t)
|
||||
case '#':
|
||||
{
|
||||
p++;
|
||||
Token *n = peek(t);
|
||||
if (n->value == TOKidentifier && n->ident == Id::line)
|
||||
Token n;
|
||||
scan(&n);
|
||||
if (n.value == TOKidentifier && n.ident == Id::line)
|
||||
{
|
||||
nextToken();
|
||||
poundLine();
|
||||
continue;
|
||||
}
|
||||
@@ -1931,45 +1884,6 @@ void Lexer::stringPostfix(Token *t)
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Read \u or \U unicode sequence
|
||||
* Input:
|
||||
* u 'u' or 'U'
|
||||
*/
|
||||
|
||||
#if 0
|
||||
unsigned Lexer::wchar(unsigned u)
|
||||
{
|
||||
unsigned value;
|
||||
unsigned n;
|
||||
unsigned char c;
|
||||
unsigned nchars;
|
||||
|
||||
nchars = (u == 'U') ? 8 : 4;
|
||||
value = 0;
|
||||
for (n = 0; 1; n++)
|
||||
{
|
||||
++p;
|
||||
if (n == nchars)
|
||||
break;
|
||||
c = *p;
|
||||
if (!ishex(c))
|
||||
{ error("\\%c sequence must be followed by %d hex characters", u, nchars);
|
||||
break;
|
||||
}
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (islower(c))
|
||||
c -= 'a' - 10;
|
||||
else
|
||||
c -= 'A' - 10;
|
||||
value <<= 4;
|
||||
value |= c;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************
|
||||
* Read in a number.
|
||||
* If it's an integer, store it in tok.TKutok.Vlong.
|
||||
@@ -1996,14 +1910,12 @@ TOK Lexer::number(Token *t)
|
||||
};
|
||||
enum FLAGS flags = FLAGS_decimal;
|
||||
|
||||
int base;
|
||||
unsigned c;
|
||||
unsigned char *start;
|
||||
TOK result;
|
||||
|
||||
//printf("Lexer::number()\n");
|
||||
state = STATE_initial;
|
||||
base = 0;
|
||||
stringbuffer.reset();
|
||||
start = p;
|
||||
while (1)
|
||||
@@ -2022,11 +1934,6 @@ TOK Lexer::number(Token *t)
|
||||
flags = (FLAGS) (flags & ~FLAGS_decimal);
|
||||
switch (c)
|
||||
{
|
||||
#if ZEROH
|
||||
case 'H': // 0h
|
||||
case 'h':
|
||||
goto hexh;
|
||||
#endif
|
||||
case 'X':
|
||||
case 'x':
|
||||
state = STATE_hex0;
|
||||
@@ -2035,15 +1942,14 @@ TOK Lexer::number(Token *t)
|
||||
case '.':
|
||||
if (p[1] == '.') // .. is a separate token
|
||||
goto done;
|
||||
#if DMDV2
|
||||
if (isalpha(p[1]) || p[1] == '_')
|
||||
goto done;
|
||||
#endif
|
||||
case 'i':
|
||||
case 'f':
|
||||
case 'F':
|
||||
goto real;
|
||||
#if ZEROH
|
||||
case 'E':
|
||||
case 'e':
|
||||
goto case_hex;
|
||||
#endif
|
||||
case 'B':
|
||||
case 'b':
|
||||
state = STATE_binary0;
|
||||
@@ -2054,14 +1960,6 @@ TOK Lexer::number(Token *t)
|
||||
state = STATE_octal;
|
||||
break;
|
||||
|
||||
#if ZEROH
|
||||
case '8': case '9': case 'A':
|
||||
case 'C': case 'D': case 'F':
|
||||
case 'a': case 'c': case 'd': case 'f':
|
||||
case_hex:
|
||||
state = STATE_hexh;
|
||||
break;
|
||||
#endif
|
||||
case '_':
|
||||
state = STATE_octal;
|
||||
p++;
|
||||
@@ -2080,12 +1978,6 @@ TOK Lexer::number(Token *t)
|
||||
case STATE_decimal: // reading decimal number
|
||||
if (!isdigit(c))
|
||||
{
|
||||
#if ZEROH
|
||||
if (ishex(c)
|
||||
|| c == 'H' || c == 'h'
|
||||
)
|
||||
goto hexh;
|
||||
#endif
|
||||
if (c == '_') // ignore embedded _
|
||||
{ p++;
|
||||
continue;
|
||||
@@ -2130,41 +2022,10 @@ TOK Lexer::number(Token *t)
|
||||
state = STATE_hex;
|
||||
break;
|
||||
|
||||
#if ZEROH
|
||||
hexh:
|
||||
state = STATE_hexh;
|
||||
case STATE_hexh: // parse numbers like 0FFh
|
||||
if (!ishex(c))
|
||||
{
|
||||
if (c == 'H' || c == 'h')
|
||||
{
|
||||
p++;
|
||||
base = 16;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for something like 1E3 or 0E24
|
||||
if (memchr((char *)stringbuffer.data, 'E', stringbuffer.offset) ||
|
||||
memchr((char *)stringbuffer.data, 'e', stringbuffer.offset))
|
||||
goto real;
|
||||
error("Hex digit expected, not '%c'", c);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case STATE_octal: // reading octal number
|
||||
case STATE_octale: // reading octal number with non-octal digits
|
||||
if (!isoctal(c))
|
||||
{
|
||||
#if ZEROH
|
||||
if (ishex(c)
|
||||
|| c == 'H' || c == 'h'
|
||||
)
|
||||
goto hexh;
|
||||
#endif
|
||||
if (c == '_') // ignore embedded _
|
||||
{ p++;
|
||||
continue;
|
||||
@@ -2186,12 +2047,6 @@ TOK Lexer::number(Token *t)
|
||||
case STATE_binary: // reading binary number
|
||||
if (c != '0' && c != '1')
|
||||
{
|
||||
#if ZEROH
|
||||
if (ishex(c)
|
||||
|| c == 'H' || c == 'h'
|
||||
)
|
||||
goto hexh;
|
||||
#endif
|
||||
if (c == '_') // ignore embedded _
|
||||
{ p++;
|
||||
continue;
|
||||
@@ -2232,7 +2087,7 @@ done:
|
||||
// Convert string to integer
|
||||
#if __DMC__
|
||||
errno = 0;
|
||||
n = strtoull((char *)stringbuffer.data,NULL,base);
|
||||
n = strtoull((char *)stringbuffer.data,NULL,0);
|
||||
if (errno == ERANGE)
|
||||
error("integer overflow");
|
||||
#else
|
||||
@@ -2636,8 +2491,9 @@ void Lexer::poundLine()
|
||||
{
|
||||
p += 8;
|
||||
filespec = mem.strdup(loc.filename ? loc.filename : mod->ident->toChars());
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
goto Lerr;
|
||||
|
||||
case '"':
|
||||
if (filespec)
|
||||
@@ -2920,7 +2776,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;
|
||||
@@ -3067,6 +2923,7 @@ static Keyword keywords[] =
|
||||
|
||||
// Added after 1.0
|
||||
{ "__argTypes", TOKargTypes },
|
||||
{ "__parameters", TOKparameters },
|
||||
{ "ref", TOKref },
|
||||
{ "macro", TOKmacro },
|
||||
#if DMDV2
|
||||
@@ -3111,7 +2968,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;
|
||||
|
||||
+2
-2
@@ -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
|
||||
@@ -156,6 +156,7 @@ enum TOK
|
||||
TOKref,
|
||||
TOKmacro,
|
||||
#if DMDV2
|
||||
TOKparameters,
|
||||
TOKtraits,
|
||||
TOKoverloadset,
|
||||
TOKpure,
|
||||
@@ -311,7 +312,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 poundLine();
|
||||
unsigned decodeUTF();
|
||||
void getDocComment(Token *t, unsigned lineComment);
|
||||
|
||||
+8
-46
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -15,53 +15,15 @@
|
||||
#pragma once
|
||||
#endif /* __DMC__ */
|
||||
|
||||
struct ObjModule;
|
||||
|
||||
struct ObjSymbol
|
||||
class Library
|
||||
{
|
||||
char *name;
|
||||
ObjModule *om;
|
||||
};
|
||||
public:
|
||||
static Library *factory();
|
||||
|
||||
#include "arraytypes.h"
|
||||
|
||||
typedef ArrayBase<ObjModule> ObjModules;
|
||||
typedef ArrayBase<ObjSymbol> ObjSymbols;
|
||||
|
||||
struct Library
|
||||
{
|
||||
File *libfile;
|
||||
ObjModules objmodules; // ObjModule[]
|
||||
ObjSymbols objsymbols; // ObjSymbol[]
|
||||
|
||||
StringTable tab;
|
||||
|
||||
Library();
|
||||
void setFilename(char *dir, char *filename);
|
||||
void addObject(const char *module_name, void *buf, size_t buflen);
|
||||
void addLibrary(void *buf, size_t buflen);
|
||||
void write();
|
||||
|
||||
private:
|
||||
void addSymbol(ObjModule *om, char *name, int pickAny = 0);
|
||||
void scanObjModule(ObjModule *om);
|
||||
unsigned short numDictPages(unsigned padding);
|
||||
int FillDict(unsigned char *bucketsP, unsigned short uNumPages);
|
||||
void WriteLibToBuffer(OutBuffer *libbuf);
|
||||
|
||||
void error(const char *format, ...)
|
||||
{
|
||||
Loc loc;
|
||||
if (libfile)
|
||||
{
|
||||
loc.filename = libfile->name->toChars();
|
||||
loc.linnum = 0;
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
::verror(loc, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
virtual void setFilename(char *dir, char *filename) = 0;
|
||||
virtual void addObject(const char *module_name, void *buf, size_t buflen) = 0;
|
||||
virtual void addLibrary(void *buf, size_t buflen) = 0;
|
||||
virtual void write() = 0;
|
||||
};
|
||||
|
||||
#endif /* DMD_LIB_H */
|
||||
|
||||
+43
-37
@@ -101,12 +101,12 @@ Global::Global()
|
||||
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
|
||||
#endif
|
||||
;
|
||||
version = "v2.059";
|
||||
version = "v2.060";
|
||||
#if IN_LLVM
|
||||
ldc_version = "LDC trunk";
|
||||
llvm_version = "LLVM "LDC_LLVM_VERSION_STRING;
|
||||
#endif
|
||||
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.
|
||||
@@ -197,7 +197,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)
|
||||
{
|
||||
@@ -208,16 +208,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);
|
||||
#if _MSC_VER
|
||||
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
|
||||
@@ -372,8 +378,8 @@ Usage:\n\
|
||||
-version=level compile in version code >= level\n\
|
||||
-version=ident compile in version code identified by ident\n\
|
||||
-vtls list all variables going into thread local storage\n\
|
||||
-w enable warnings\n\
|
||||
-wi enable informational warnings\n\
|
||||
-w warnings as errors (compilation will halt)\n\
|
||||
-wi warnings as messages (compilation will continue)\n\
|
||||
-X generate JSON file\n\
|
||||
-Xffilename write JSON file to filename\n\
|
||||
", fpic);
|
||||
@@ -1040,7 +1046,7 @@ int tryMain(int argc, char *argv[])
|
||||
{
|
||||
for (size_t i = 0; i < global.params.fileImppath->dim; i++)
|
||||
{
|
||||
char *path = global.params.fileImppath->tdata()[i];
|
||||
char *path = (*global.params.fileImppath)[i];
|
||||
Strings *a = FileName::splitPath(path);
|
||||
|
||||
if (a)
|
||||
@@ -1061,7 +1067,7 @@ int tryMain(int argc, char *argv[])
|
||||
char *ext;
|
||||
char *name;
|
||||
|
||||
p = files.tdata()[i];
|
||||
p = files[i];
|
||||
|
||||
#if _WIN32
|
||||
// Convert / to \ so linker will work
|
||||
@@ -1079,47 +1085,47 @@ int tryMain(int argc, char *argv[])
|
||||
*/
|
||||
if (FileName::equals(ext, global.obj_ext))
|
||||
{
|
||||
global.params.objfiles->push(files.tdata()[i]);
|
||||
libmodules.push(files.tdata()[i]);
|
||||
global.params.objfiles->push(files[i]);
|
||||
libmodules.push(files[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FileName::equals(ext, global.lib_ext))
|
||||
{
|
||||
global.params.libfiles->push(files.tdata()[i]);
|
||||
libmodules.push(files.tdata()[i]);
|
||||
global.params.libfiles->push(files[i]);
|
||||
libmodules.push(files[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(ext, global.ddoc_ext) == 0)
|
||||
{
|
||||
global.params.ddocfiles->push(files.tdata()[i]);
|
||||
global.params.ddocfiles->push(files[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FileName::equals(ext, global.json_ext))
|
||||
{
|
||||
global.params.doXGeneration = 1;
|
||||
global.params.xfilename = files.tdata()[i];
|
||||
global.params.xfilename = files[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FileName::equals(ext, global.map_ext))
|
||||
{
|
||||
global.params.mapfile = files.tdata()[i];
|
||||
global.params.mapfile = files[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
#if TARGET_WINDOS
|
||||
if (FileName::equals(ext, "res"))
|
||||
{
|
||||
global.params.resfile = files.tdata()[i];
|
||||
global.params.resfile = files[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FileName::equals(ext, "def"))
|
||||
{
|
||||
global.params.deffile = files.tdata()[i];
|
||||
global.params.deffile = files[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1134,10 +1140,7 @@ int tryMain(int argc, char *argv[])
|
||||
*/
|
||||
if (FileName::equals(ext, global.mars_ext) ||
|
||||
FileName::equals(ext, global.hdr_ext) ||
|
||||
FileName::equals(ext, "dd") ||
|
||||
FileName::equals(ext, "htm") ||
|
||||
FileName::equals(ext, "html") ||
|
||||
FileName::equals(ext, "xhtml"))
|
||||
FileName::equals(ext, "dd"))
|
||||
{
|
||||
ext--; // skip onto '.'
|
||||
assert(*ext == '.');
|
||||
@@ -1150,7 +1153,7 @@ int tryMain(int argc, char *argv[])
|
||||
strcmp(name, ".") == 0)
|
||||
{
|
||||
Linvalid:
|
||||
error(0, "invalid file name '%s'", files.tdata()[i]);
|
||||
error(0, "invalid file name '%s'", files[i]);
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
@@ -1232,7 +1235,7 @@ int tryMain(int argc, char *argv[])
|
||||
// Remove m's object file from list of object files
|
||||
for (size_t j = 0; j < global.params.objfiles->dim; j++)
|
||||
{
|
||||
if (m->objfile->name->str == global.params.objfiles->tdata()[j])
|
||||
if (m->objfile->name->str == (*global.params.objfiles)[j])
|
||||
{
|
||||
global.params.objfiles->remove(j);
|
||||
break;
|
||||
@@ -1322,24 +1325,13 @@ int tryMain(int argc, char *argv[])
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
if (global.params.moduleDeps != NULL)
|
||||
{
|
||||
assert(global.params.moduleDepsFile != NULL);
|
||||
|
||||
File deps(global.params.moduleDepsFile);
|
||||
OutBuffer* ob = global.params.moduleDeps;
|
||||
deps.setbuffer((void*)ob->data, ob->offset);
|
||||
deps.writev();
|
||||
}
|
||||
|
||||
|
||||
// Scan for functions to inline
|
||||
if (global.params.useInline)
|
||||
{
|
||||
/* The problem with useArrayBounds and useAssert is that the
|
||||
* module being linked to may not have generated them, so if
|
||||
* we inline functions from those modules, the symbols for them will
|
||||
* not be found at link time.
|
||||
* We must do this BEFORE generating the .deps file!
|
||||
*/
|
||||
if (!global.params.useArrayBounds && !global.params.useAssert)
|
||||
{
|
||||
@@ -1355,7 +1347,21 @@ int tryMain(int argc, char *argv[])
|
||||
if (global.errors)
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
||||
if (global.params.moduleDeps != NULL)
|
||||
{
|
||||
assert(global.params.moduleDepsFile != NULL);
|
||||
|
||||
File deps(global.params.moduleDepsFile);
|
||||
OutBuffer* ob = global.params.moduleDeps;
|
||||
deps.setbuffer((void*)ob->data, ob->offset);
|
||||
deps.writev();
|
||||
}
|
||||
|
||||
// Scan for functions to inline
|
||||
if (global.params.useInline)
|
||||
{
|
||||
for (size_t i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = modules[i];
|
||||
@@ -1374,7 +1380,7 @@ int tryMain(int argc, char *argv[])
|
||||
Library *library = NULL;
|
||||
if (global.params.lib)
|
||||
{
|
||||
library = new Library();
|
||||
library = Library::factory();
|
||||
library->setFilename(global.params.objdir, global.params.libname);
|
||||
|
||||
// Add input object and input library files to output library
|
||||
@@ -1405,7 +1411,7 @@ int tryMain(int argc, char *argv[])
|
||||
}
|
||||
if (!global.errors && modules.dim)
|
||||
{
|
||||
obj_end(library, modules.tdata()[0]->objfile);
|
||||
obj_end(library, modules[0]->objfile);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+13
-5
@@ -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
|
||||
@@ -97,11 +97,13 @@ void unittests();
|
||||
|
||||
#define DMDV1 0
|
||||
#define DMDV2 1 // 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
|
||||
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
|
||||
#define BUG6652 1 // Making foreach range statement parameter non-ref in default
|
||||
// 1: Modifying iteratee in body is warned with -w switch
|
||||
// 2: Modifying iteratee in body is error without -d switch
|
||||
|
||||
// Set if C++ mangling is done by the front end
|
||||
#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS))
|
||||
@@ -279,6 +281,10 @@ 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;
|
||||
@@ -303,7 +309,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;
|
||||
#if IN_LLVM
|
||||
char *ldc_version;
|
||||
@@ -475,7 +483,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, 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);
|
||||
void fatal();
|
||||
@@ -495,7 +503,7 @@ void util_progress();
|
||||
#endif
|
||||
|
||||
/*** Where to send error messages ***/
|
||||
#if IN_GCC || IN_LLVM
|
||||
#if defined(IN_GCC) || IN_LLVM
|
||||
#define stdmsg stderr
|
||||
#else
|
||||
#define stdmsg stderr
|
||||
|
||||
+35
-62
@@ -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
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
#include "gdc_alloca.h"
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,10 @@
|
||||
#include "hdrgen.h"
|
||||
#include "lexer.h"
|
||||
|
||||
#include "html.h"
|
||||
// stricmp
|
||||
#if __GNUC__ && !_WIN32
|
||||
#include "gnuc.h"
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-dmd-gcc.h"
|
||||
@@ -88,7 +91,6 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
||||
errors = 0;
|
||||
numlines = 0;
|
||||
members = NULL;
|
||||
isHtml = 0;
|
||||
isDocFile = 0;
|
||||
needmoduleinfo = 0;
|
||||
#ifdef IN_GCC
|
||||
@@ -146,17 +148,8 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
||||
!srcfilename->equalsExt(global.hdr_ext) &&
|
||||
!srcfilename->equalsExt("dd"))
|
||||
{
|
||||
if (srcfilename->equalsExt("html") ||
|
||||
srcfilename->equalsExt("htm") ||
|
||||
srcfilename->equalsExt("xhtml"))
|
||||
{ if (!global.params.useDeprecated)
|
||||
error("html source files is deprecated %s", srcfilename->toChars());
|
||||
isHtml = 1;
|
||||
}
|
||||
else
|
||||
{ error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
|
||||
fatal();
|
||||
}
|
||||
error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
|
||||
fatal();
|
||||
}
|
||||
#if !IN_LLVM
|
||||
char *argobj;
|
||||
@@ -438,7 +431,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
|
||||
@@ -499,7 +492,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());
|
||||
}
|
||||
}
|
||||
@@ -530,7 +523,7 @@ bool Module::read(Loc loc)
|
||||
{
|
||||
for (size_t i = 0; i < global.path->dim; i++)
|
||||
{
|
||||
char *p = global.path->tdata()[i];
|
||||
char *p = (*global.path)[i];
|
||||
fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p);
|
||||
}
|
||||
}
|
||||
@@ -579,24 +572,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)
|
||||
{
|
||||
@@ -609,7 +595,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)
|
||||
@@ -760,7 +747,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);
|
||||
}
|
||||
@@ -779,19 +766,6 @@ void Module::parse()
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (isHtml)
|
||||
{
|
||||
OutBuffer *dbuf = new OutBuffer();
|
||||
Html h(srcname, buf, buflen);
|
||||
h.extractCode(dbuf);
|
||||
buf = dbuf->data;
|
||||
buflen = dbuf->offset;
|
||||
#ifdef IN_GCC
|
||||
// dump extracted source
|
||||
if (dump_source)
|
||||
d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
|
||||
#endif
|
||||
}
|
||||
#if IN_LLVM
|
||||
Parser p(this, buf, buflen, gen_docs);
|
||||
#else
|
||||
@@ -890,7 +864,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);
|
||||
}
|
||||
}
|
||||
@@ -903,13 +877,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);
|
||||
}
|
||||
|
||||
@@ -964,7 +938,7 @@ void Module::semantic(Scope* unused_sc)
|
||||
|
||||
// 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);
|
||||
@@ -972,7 +946,7 @@ void Module::semantic(Scope* unused_sc)
|
||||
|
||||
// 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);
|
||||
@@ -993,7 +967,7 @@ void Module::semantic2(Scope* unused_sc)
|
||||
{
|
||||
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");
|
||||
}
|
||||
@@ -1017,7 +991,7 @@ void Module::semantic2(Scope* unused_sc)
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s;
|
||||
|
||||
s = members->tdata()[i];
|
||||
s = (*members)[i];
|
||||
s->semantic2(sc);
|
||||
}
|
||||
|
||||
@@ -1045,7 +1019,7 @@ void Module::semantic3(Scope* unused_sc)
|
||||
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);
|
||||
}
|
||||
@@ -1068,7 +1042,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());
|
||||
|
||||
@@ -1093,7 +1067,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);
|
||||
}
|
||||
@@ -1154,7 +1128,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;
|
||||
}
|
||||
}
|
||||
@@ -1168,7 +1142,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;
|
||||
@@ -1238,7 +1212,6 @@ void Module::runDeferredSemantic()
|
||||
int Module::imports(Module *m)
|
||||
{
|
||||
//printf("%s Module::imports(%s)\n", toChars(), m->toChars());
|
||||
int aimports_dim = aimports.dim;
|
||||
#if 0
|
||||
for (size_t i = 0; i < aimports.dim; i++)
|
||||
{ Module *mi = (Module *)aimports.data[i];
|
||||
@@ -1246,7 +1219,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)
|
||||
@@ -1270,7 +1243,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;
|
||||
}
|
||||
@@ -1278,7 +1251,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;
|
||||
}
|
||||
@@ -1303,7 +1276,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('.');
|
||||
@@ -1340,7 +1313,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);
|
||||
|
||||
@@ -79,7 +79,6 @@ struct Module : Package
|
||||
|
||||
unsigned errors; // if any errors in file
|
||||
unsigned numlines; // number of lines in source file
|
||||
int isHtml; // if it is an HTML file
|
||||
int isDocFile; // if it is a documentation input file, not D source
|
||||
int needmoduleinfo;
|
||||
#ifdef IN_GCC
|
||||
@@ -141,8 +140,6 @@ 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 parse(bool dump_source = false); // syntactic parse
|
||||
#else
|
||||
void parse(); // syntactic parse
|
||||
#endif
|
||||
|
||||
+283
-193
File diff suppressed because it is too large
Load Diff
+11
-6
@@ -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
|
||||
@@ -48,7 +48,7 @@ struct HdrGenState;
|
||||
struct Parameter;
|
||||
|
||||
// Back end
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node TYPE;
|
||||
typedef TYPE type;
|
||||
#endif
|
||||
@@ -215,6 +215,7 @@ struct Type : Object
|
||||
static ClassDeclaration *typeinfowild;
|
||||
|
||||
static TemplateDeclaration *associativearray;
|
||||
static TemplateDeclaration *rtinfo;
|
||||
|
||||
static Type *basic[TMAX];
|
||||
static unsigned char mangleChar[TMAX];
|
||||
@@ -317,8 +318,8 @@ struct Type : Object
|
||||
virtual ClassDeclaration *isClassHandle();
|
||||
virtual Expression *getProperty(Loc loc, Identifier *ident);
|
||||
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
virtual structalign_t alignment();
|
||||
Expression *noMember(Scope *sc, Expression *e, Identifier *ident);
|
||||
virtual unsigned memalign(unsigned salign);
|
||||
virtual Expression *defaultInit(Loc loc = 0);
|
||||
virtual Expression *defaultInitLiteral(Loc loc);
|
||||
virtual Expression *voidInitLiteral(VarDeclaration *var);
|
||||
@@ -375,6 +376,7 @@ struct TypeError : Type
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
Expression *defaultInit(Loc loc);
|
||||
Expression *defaultInitLiteral(Loc loc);
|
||||
TypeTuple *toArgTypes();
|
||||
};
|
||||
|
||||
struct TypeNext : Type
|
||||
@@ -409,7 +411,7 @@ struct TypeBasic : Type
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
#if IN_LLVM
|
||||
unsigned memalign(unsigned salign);
|
||||
unsigned alignment();
|
||||
#endif
|
||||
Expression *getProperty(Loc loc, Identifier *ident);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
@@ -488,7 +490,7 @@ struct TypeSArray : TypeArray
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
int isString();
|
||||
int isZeroInit(Loc loc);
|
||||
unsigned memalign(unsigned salign);
|
||||
structalign_t alignment();
|
||||
MATCH constConv(Type *to);
|
||||
MATCH implicitConvTo(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
@@ -567,6 +569,7 @@ struct TypeAArray : TypeArray
|
||||
int isZeroInit(Loc loc);
|
||||
int checkBoolean();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Type *reliesOnTident(TemplateParameters *tparams);
|
||||
Expression *toExpression();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
@@ -778,6 +781,7 @@ struct TypeInstance : TypeQualified
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
Type *reliesOnTident(TemplateParameters *tparams = NULL);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
|
||||
};
|
||||
|
||||
@@ -817,7 +821,7 @@ struct TypeStruct : Type
|
||||
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
unsigned memalign(unsigned salign);
|
||||
structalign_t alignment();
|
||||
Expression *defaultInit(Loc loc);
|
||||
Expression *defaultInitLiteral(Loc loc);
|
||||
Expression *voidInitLiteral(VarDeclaration *var);
|
||||
@@ -907,6 +911,7 @@ struct TypeTypedef : Type
|
||||
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
structalign_t alignment();
|
||||
Expression *getProperty(Loc loc, Identifier *ident);
|
||||
int isintegral();
|
||||
int isfloating();
|
||||
|
||||
+91
-60
@@ -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
|
||||
@@ -355,9 +356,11 @@ Expression *UnaExp::op_overload(Scope *sc)
|
||||
/* Rewrite op(e1) as:
|
||||
* op(e1.aliasthis)
|
||||
*/
|
||||
UnaExp *e = (UnaExp *)syntaxCopy();
|
||||
e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((UnaExp *)e)->e1 = e1;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -374,7 +377,7 @@ Expression *ArrayExp::op_overload(Scope *sc)
|
||||
if (fd)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *x = arguments->tdata()[i];
|
||||
{ Expression *x = (*arguments)[i];
|
||||
// Create scope for '$' variable for this dimension
|
||||
ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, this);
|
||||
sym->loc = loc;
|
||||
@@ -393,7 +396,7 @@ Expression *ArrayExp::op_overload(Scope *sc)
|
||||
x = new CommaExp(0, av, x);
|
||||
x->semantic(sc);
|
||||
}
|
||||
arguments->tdata()[i] = x;
|
||||
(*arguments)[i] = x;
|
||||
sc = sc->pop();
|
||||
}
|
||||
|
||||
@@ -412,9 +415,11 @@ Expression *ArrayExp::op_overload(Scope *sc)
|
||||
/* Rewrite op(e1) as:
|
||||
* op(e1.aliasthis)
|
||||
*/
|
||||
UnaExp *e = (UnaExp *)syntaxCopy();
|
||||
e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((UnaExp *)e)->e1 = e1;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -457,9 +462,11 @@ Expression *CastExp::op_overload(Scope *sc)
|
||||
/* Rewrite op(e1) as:
|
||||
* op(e1.aliasthis)
|
||||
*/
|
||||
UnaExp *e = (UnaExp *)syntaxCopy();
|
||||
e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((UnaExp *)e)->e1 = e1;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -529,9 +536,9 @@ Expression *BinExp::op_overload(Scope *sc)
|
||||
*/
|
||||
|
||||
args1.setDim(1);
|
||||
args1.tdata()[0] = e1;
|
||||
args1[0] = e1;
|
||||
args2.setDim(1);
|
||||
args2.tdata()[0] = e2;
|
||||
args2[0] = e2;
|
||||
argsset = 1;
|
||||
|
||||
Match m;
|
||||
@@ -622,9 +629,9 @@ L1:
|
||||
|
||||
if (!argsset)
|
||||
{ args1.setDim(1);
|
||||
args1.tdata()[0] = e1;
|
||||
args1[0] = e1;
|
||||
args2.setDim(1);
|
||||
args2.tdata()[0] = e2;
|
||||
args2[0] = e2;
|
||||
}
|
||||
|
||||
Match m;
|
||||
@@ -715,9 +722,11 @@ L1:
|
||||
/* Rewrite (e1 op e2) as:
|
||||
* (e1.aliasthis op e2)
|
||||
*/
|
||||
BinExp *e = (BinExp *)syntaxCopy();
|
||||
e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((BinExp *)e)->e1 = e1;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
// Try alias this on second operand
|
||||
@@ -730,9 +739,11 @@ L1:
|
||||
/* Rewrite (e1 op e2) as:
|
||||
* (e1 op e2.aliasthis)
|
||||
*/
|
||||
BinExp *e = (BinExp *)syntaxCopy();
|
||||
e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((BinExp *)e)->e2 = e2;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
@@ -776,9 +787,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
|
||||
Expressions args2;
|
||||
|
||||
args1.setDim(1);
|
||||
args1.tdata()[0] = e1;
|
||||
args1[0] = e1;
|
||||
args2.setDim(1);
|
||||
args2.tdata()[0] = e2;
|
||||
args2[0] = e2;
|
||||
|
||||
Match m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
@@ -884,9 +895,11 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
|
||||
/* Rewrite (e1 op e2) as:
|
||||
* (e1.aliasthis op e2)
|
||||
*/
|
||||
BinExp *e = (BinExp *)syntaxCopy();
|
||||
e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((BinExp *)e)->e1 = e1;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
// Try alias this on second operand
|
||||
@@ -895,9 +908,11 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
|
||||
/* Rewrite (e1 op e2) as:
|
||||
* (e1 op e2.aliasthis)
|
||||
*/
|
||||
BinExp *e = (BinExp *)syntaxCopy();
|
||||
e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((BinExp *)e)->e2 = e2;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -916,12 +931,20 @@ Expression *EqualExp::op_overload(Scope *sc)
|
||||
if (!(cd1->isCPPinterface() || cd2->isCPPinterface()))
|
||||
{
|
||||
/* Rewrite as:
|
||||
* .object.opEquals(cast(Object)e1, cast(Object)e2)
|
||||
* .object.opEquals(e1, e2)
|
||||
*/
|
||||
Expression *e1x = e1;
|
||||
Expression *e2x = e2;
|
||||
|
||||
/*
|
||||
* The explicit cast is necessary for interfaces,
|
||||
* see http://d.puremagic.com/issues/show_bug.cgi?id=4088
|
||||
*/
|
||||
Expression *e1x = new CastExp(loc, e1, ClassDeclaration::object->getType());
|
||||
Expression *e2x = new CastExp(loc, e2, ClassDeclaration::object->getType());
|
||||
Type *to = ClassDeclaration::object->getType();
|
||||
if (cd1->isInterfaceDeclaration())
|
||||
e1x = new CastExp(loc, e1, t1->isMutable() ? to : to->constOf());
|
||||
if (cd2->isInterfaceDeclaration())
|
||||
e2x = new CastExp(loc, e2, t2->isMutable() ? to : to->constOf());
|
||||
|
||||
Expression *e = new IdentifierExp(loc, Id::empty);
|
||||
e = new DotIdExp(loc, e, Id::object);
|
||||
@@ -968,7 +991,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
||||
Expressions *a = new Expressions();
|
||||
a->push(e2);
|
||||
for (size_t i = 0; i < ae->arguments->dim; i++)
|
||||
a->push(ae->arguments->tdata()[i]);
|
||||
a->push((*ae->arguments)[i]);
|
||||
|
||||
Objects *targsi = opToArg(sc, op);
|
||||
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi);
|
||||
@@ -1085,7 +1108,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
||||
*/
|
||||
|
||||
args2.setDim(1);
|
||||
args2.tdata()[0] = e2;
|
||||
args2[0] = e2;
|
||||
|
||||
Match m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
@@ -1132,9 +1155,11 @@ L1:
|
||||
/* Rewrite (e1 op e2) as:
|
||||
* (e1.aliasthis op e2)
|
||||
*/
|
||||
BinExp *e = (BinExp *)syntaxCopy();
|
||||
e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((BinExp *)e)->e1 = e1;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
// Try alias this on second operand
|
||||
@@ -1144,9 +1169,11 @@ L1:
|
||||
/* Rewrite (e1 op e2) as:
|
||||
* (e1 op e2.aliasthis)
|
||||
*/
|
||||
BinExp *e = (BinExp *)syntaxCopy();
|
||||
e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident);
|
||||
return e->trySemantic(sc);
|
||||
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
|
||||
Expression *e = copy();
|
||||
((BinExp *)e)->e2 = e2;
|
||||
e = e->trySemantic(sc);
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
@@ -1209,7 +1236,7 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
|
||||
{
|
||||
Identifier *idapply = (op == TOKforeach) ? Id::apply : Id::applyReverse;
|
||||
#if DMDV2
|
||||
Identifier *idhead = (op == TOKforeach) ? Id::Ffront : Id::Fback;
|
||||
Identifier *idfront = (op == TOKforeach) ? Id::Ffront : Id::Fback;
|
||||
int sliced = 0;
|
||||
#endif
|
||||
Type *tab;
|
||||
@@ -1262,7 +1289,7 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
|
||||
}
|
||||
}
|
||||
|
||||
if (Dsymbol *shead = search_function(ad, idhead))
|
||||
if (Dsymbol *shead = ad->search(0, idfront, 0))
|
||||
{ // range aggregate
|
||||
break;
|
||||
}
|
||||
@@ -1316,7 +1343,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
|
||||
if (sapply) // prefer opApply
|
||||
{
|
||||
for (size_t u = 0; u < arguments->dim; u++)
|
||||
{ Parameter *arg = arguments->tdata()[u];
|
||||
{ Parameter *arg = (*arguments)[u];
|
||||
if (arg->type)
|
||||
arg->type = arg->type->semantic(loc, sc);
|
||||
}
|
||||
@@ -1350,14 +1377,14 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
|
||||
/* Return if no arguments need types.
|
||||
*/
|
||||
for (size_t u = 0; u < arguments->dim; u++)
|
||||
{ Parameter *arg = arguments->tdata()[u];
|
||||
{ Parameter *arg = (*arguments)[u];
|
||||
if (!arg->type)
|
||||
break;
|
||||
}
|
||||
|
||||
AggregateDeclaration *ad;
|
||||
|
||||
Parameter *arg = arguments->tdata()[0];
|
||||
Parameter *arg = (*arguments)[0];
|
||||
Type *taggr = aggr->type;
|
||||
assert(taggr);
|
||||
Type *tab = taggr->toBasetype();
|
||||
@@ -1370,7 +1397,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
|
||||
{
|
||||
if (!arg->type)
|
||||
arg->type = Type::tsize_t; // key type
|
||||
arg = arguments->tdata()[1];
|
||||
arg = (*arguments)[1];
|
||||
}
|
||||
if (!arg->type && tab->ty != Ttuple)
|
||||
arg->type = tab->nextOf(); // value type
|
||||
@@ -1383,7 +1410,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
|
||||
{
|
||||
if (!arg->type)
|
||||
arg->type = taa->index; // key type
|
||||
arg = arguments->tdata()[1];
|
||||
arg = (*arguments)[1];
|
||||
}
|
||||
if (!arg->type)
|
||||
arg->type = taa->next; // value type
|
||||
@@ -1403,20 +1430,24 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
|
||||
{
|
||||
if (!arg->type)
|
||||
{
|
||||
/* Look for a head() or rear() overload
|
||||
/* Look for a front() or back() overload
|
||||
*/
|
||||
Identifier *id = (op == TOKforeach) ? Id::Ffront : Id::Fback;
|
||||
Dsymbol *s = search_function(ad, id);
|
||||
Dsymbol *s = ad->search(0, id, 0);
|
||||
FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
|
||||
if (!fd)
|
||||
{ if (s && s->isTemplateDeclaration())
|
||||
break;
|
||||
break;
|
||||
if (fd)
|
||||
{
|
||||
// Resolve inout qualifier of front type
|
||||
arg->type = fd->type->nextOf();
|
||||
if (arg->type)
|
||||
arg->type = arg->type->substWildTo(tab->mod);
|
||||
}
|
||||
// Resolve inout qualifier of front type
|
||||
arg->type = fd->type->nextOf();
|
||||
if (arg->type)
|
||||
arg->type = arg->type->substWildTo(tab->mod);
|
||||
else if (s && s->isTemplateDeclaration())
|
||||
;
|
||||
else if (s && s->isDeclaration())
|
||||
arg->type = ((Declaration *)s)->type;
|
||||
else
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1522,7 +1553,7 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flag
|
||||
|
||||
for (size_t u = 0; u < nparams; u++)
|
||||
{
|
||||
Parameter *arg = arguments->tdata()[u];
|
||||
Parameter *arg = (*arguments)[u];
|
||||
Parameter *param = Parameter::getNth(tf->parameters, u);
|
||||
if (arg->type)
|
||||
{ if (!arg->type->equals(param->type))
|
||||
@@ -1560,7 +1591,7 @@ void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments)
|
||||
}
|
||||
if (!td->parameters || td->parameters->dim != 1)
|
||||
continue;
|
||||
TemplateParameter *tp = td->parameters->tdata()[0];
|
||||
TemplateParameter *tp = (*td->parameters)[0];
|
||||
TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
|
||||
if (!tap || !tap->specType || tap->specType->ty != Tfunction)
|
||||
continue;
|
||||
|
||||
+16
-17
@@ -153,7 +153,6 @@ Expression *fromConstInitializer(int result, Expression *e1)
|
||||
if (e1->op == TOKvar)
|
||||
{ VarExp *ve = (VarExp *)e1;
|
||||
VarDeclaration *v = ve->var->isVarDeclaration();
|
||||
int fwdref = (v && !v->originalType && v->scope);
|
||||
e = expandVar(result, v);
|
||||
if (e)
|
||||
{
|
||||
@@ -202,10 +201,10 @@ Expression *VarExp::optimize(int result)
|
||||
Expression *TupleExp::optimize(int result)
|
||||
{
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = exps->tdata()[i];
|
||||
{ Expression *e = (*exps)[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
exps->tdata()[i] = e;
|
||||
(*exps)[i] = e;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -215,10 +214,10 @@ Expression *ArrayLiteralExp::optimize(int result)
|
||||
if (elements)
|
||||
{
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = elements->tdata()[i];
|
||||
{ Expression *e = (*elements)[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
elements->tdata()[i] = e;
|
||||
(*elements)[i] = e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@@ -228,14 +227,14 @@ Expression *AssocArrayLiteralExp::optimize(int result)
|
||||
{
|
||||
assert(keys->dim == values->dim);
|
||||
for (size_t i = 0; i < keys->dim; i++)
|
||||
{ Expression *e = keys->tdata()[i];
|
||||
{ Expression *e = (*keys)[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
keys->tdata()[i] = e;
|
||||
(*keys)[i] = e;
|
||||
|
||||
e = values->tdata()[i];
|
||||
e = (*values)[i];
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
values->tdata()[i] = e;
|
||||
(*values)[i] = e;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -245,11 +244,11 @@ Expression *StructLiteralExp::optimize(int result)
|
||||
if (elements)
|
||||
{
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = elements->tdata()[i];
|
||||
{ Expression *e = (*elements)[i];
|
||||
if (!e)
|
||||
continue;
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
elements->tdata()[i] = e;
|
||||
(*elements)[i] = e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@@ -495,20 +494,20 @@ Expression *NewExp::optimize(int result)
|
||||
if (newargs)
|
||||
{
|
||||
for (size_t i = 0; i < newargs->dim; i++)
|
||||
{ Expression *e = newargs->tdata()[i];
|
||||
{ Expression *e = (*newargs)[i];
|
||||
|
||||
e = e->optimize(WANTvalue);
|
||||
newargs->tdata()[i] = e;
|
||||
(*newargs)[i] = e;
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = arguments->tdata()[i];
|
||||
{ Expression *e = (*arguments)[i];
|
||||
|
||||
e = e->optimize(WANTvalue);
|
||||
arguments->tdata()[i] = e;
|
||||
(*arguments)[i] = e;
|
||||
}
|
||||
}
|
||||
if (result & WANTinterpret)
|
||||
@@ -527,10 +526,10 @@ Expression *CallExp::optimize(int result)
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = arguments->tdata()[i];
|
||||
{ Expression *e = (*arguments)[i];
|
||||
|
||||
e = e->optimize(WANTvalue);
|
||||
arguments->tdata()[i] = e;
|
||||
(*arguments)[i] = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-11
@@ -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 <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h> // strlen(),memcpy()
|
||||
|
||||
#include "rmem.h"
|
||||
#include "lexer.h"
|
||||
@@ -454,7 +455,10 @@ Dsymbols *Parser::parseDeclDefs(int once)
|
||||
((tk = peek(tk)), 1) &&
|
||||
skipAttributes(tk, &tk) &&
|
||||
(tk->value == TOKlparen ||
|
||||
tk->value == TOKlcurly)
|
||||
tk->value == TOKlcurly ||
|
||||
tk->value == TOKin ||
|
||||
tk->value == TOKout ||
|
||||
tk->value == TOKbody)
|
||||
)
|
||||
{
|
||||
a = parseDeclarations(storageClass, comment);
|
||||
@@ -512,7 +516,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;
|
||||
@@ -535,7 +543,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;
|
||||
@@ -1370,7 +1378,8 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl)
|
||||
default:
|
||||
Ldefault:
|
||||
{ stc = storageClass & (STCin | STCout | STCref | STClazy);
|
||||
if (stc & (stc - 1)) // if stc is not a power of 2
|
||||
if (stc & (stc - 1) && // if stc is not a power of 2
|
||||
!(stc == (STCin | STCref)))
|
||||
error("incompatible parameter storage classes");
|
||||
if ((storageClass & (STCconst | STCout)) == (STCconst | STCout))
|
||||
error("out cannot be const");
|
||||
@@ -2860,7 +2869,10 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c
|
||||
((tk = peek(tk)), 1) &&
|
||||
skipAttributes(tk, &tk) &&
|
||||
(tk->value == TOKlparen ||
|
||||
tk->value == TOKlcurly)
|
||||
tk->value == TOKlcurly ||
|
||||
tk->value == TOKin ||
|
||||
tk->value == TOKout ||
|
||||
tk->value == TOKbody)
|
||||
)
|
||||
{
|
||||
ts = NULL;
|
||||
@@ -3347,7 +3359,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;
|
||||
|
||||
@@ -3601,7 +3621,7 @@ Statement *Parser::parseStatement(int flags)
|
||||
as->reserve(a->dim);
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{
|
||||
Dsymbol *d = a->tdata()[i];
|
||||
Dsymbol *d = (*a)[i];
|
||||
s = new ExpStatement(loc, d);
|
||||
as->push(s);
|
||||
}
|
||||
@@ -3609,7 +3629,7 @@ Statement *Parser::parseStatement(int flags)
|
||||
}
|
||||
else if (a->dim == 1)
|
||||
{
|
||||
Dsymbol *d = a->tdata()[0];
|
||||
Dsymbol *d = (*a)[0];
|
||||
s = new ExpStatement(loc, d);
|
||||
}
|
||||
else
|
||||
@@ -3841,7 +3861,7 @@ Statement *Parser::parseStatement(int flags)
|
||||
Expression *aggr = parseExpression();
|
||||
if (token.value == TOKslice && arguments->dim == 1)
|
||||
{
|
||||
Parameter *a = arguments->tdata()[0];
|
||||
Parameter *a = (*arguments)[0];
|
||||
delete arguments;
|
||||
nextToken();
|
||||
Expression *upr = parseExpression();
|
||||
@@ -4087,7 +4107,7 @@ Statement *Parser::parseStatement(int flags)
|
||||
// Keep cases in order by building the case statements backwards
|
||||
for (size_t i = cases.dim; i; i--)
|
||||
{
|
||||
exp = cases.tdata()[i - 1];
|
||||
exp = cases[i - 1];
|
||||
s = new CaseStatement(loc, exp, s);
|
||||
}
|
||||
}
|
||||
@@ -4242,7 +4262,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;
|
||||
@@ -5406,6 +5426,7 @@ Expression *Parser::parsePrimaryExp()
|
||||
token.value == TOKenum ||
|
||||
token.value == TOKinterface ||
|
||||
token.value == TOKargTypes ||
|
||||
token.value == TOKparameters ||
|
||||
#if DMDV2
|
||||
token.value == TOKconst && peek(&token)->value == TOKrparen ||
|
||||
token.value == TOKinvariant && peek(&token)->value == TOKrparen ||
|
||||
|
||||
+3
-1
@@ -12,7 +12,9 @@ of the D Programming Language defined in the documents at
|
||||
http://www.digitalmars.com/d/
|
||||
|
||||
These sources are free, they are redistributable and modifiable
|
||||
under the terms of the GNU General Public License (attached as gpl.txt),
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version (attached as gpl.txt),
|
||||
or the Artistic License (attached as artistic.txt).
|
||||
|
||||
The optimizer and code generator sources are
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
|
||||
// Copyright (c) 2010-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
/**
|
||||
* Implementation of associative arrays.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
|
||||
// Copyright (c) 2010-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
typedef void* Value;
|
||||
typedef void* Key;
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
#include "port.h"
|
||||
#include "root.h"
|
||||
#include "dchar.h"
|
||||
#include "rmem.h"
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
|
||||
// Copyright (c) 2009-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#define _MT 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -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
|
||||
@@ -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,4 +1,12 @@
|
||||
|
||||
// Copyright (c) 2009-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
// Put functions in here missing from gnu C
|
||||
|
||||
#include "gnuc.h"
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
|
||||
// Copyright (c) 2009-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef _GNUC_H
|
||||
#define _GNUC_H 1
|
||||
|
||||
|
||||
@@ -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
|
||||
+18
-1
@@ -109,6 +109,7 @@ int response_expand(int *pargc, char ***pargv)
|
||||
char *buffer;
|
||||
char *bufend;
|
||||
char *p;
|
||||
int comment = 0;
|
||||
|
||||
cp++;
|
||||
p = getenv(cp);
|
||||
@@ -171,15 +172,31 @@ int response_expand(int *pargc, char ***pargv)
|
||||
goto L2;
|
||||
|
||||
case 0xD:
|
||||
case '\n':
|
||||
if (comment)
|
||||
{
|
||||
comment = 0;
|
||||
}
|
||||
case 0:
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
continue; // scan to start of argument
|
||||
|
||||
case '#':
|
||||
comment = 1;
|
||||
continue;
|
||||
|
||||
case '@':
|
||||
if (comment)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
recurse = 1;
|
||||
default: /* start of new argument */
|
||||
if (comment)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (addargp(&n,p))
|
||||
goto noexpand;
|
||||
instring = 0;
|
||||
|
||||
+7
-2
@@ -1,6 +1,11 @@
|
||||
|
||||
/* Copyright (c) 2000 Digital Mars */
|
||||
/* All Rights Reserved */
|
||||
// Copyright (c) 2000-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
+7
-1
@@ -1,5 +1,11 @@
|
||||
// Copyright (C) 2000-2011 by Digital Mars
|
||||
|
||||
// Copyright (c) 2000-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#ifndef ROOT_MEM_H
|
||||
#define ROOT_MEM_H
|
||||
|
||||
+2
-116
@@ -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"
|
||||
|
||||
#if 0 //__SC__ //def DEBUG
|
||||
@@ -142,22 +142,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");
|
||||
@@ -206,15 +190,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;
|
||||
@@ -1609,30 +1584,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;
|
||||
|
||||
@@ -1646,18 +1597,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)
|
||||
@@ -1719,13 +1662,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);
|
||||
@@ -1873,46 +1809,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;
|
||||
@@ -1921,16 +1817,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
|
||||
@@ -24,7 +23,6 @@
|
||||
typedef size_t hash_t;
|
||||
|
||||
#include "longdouble.h"
|
||||
#include "dchar.h"
|
||||
|
||||
char *wchar2ascii(wchar_t *);
|
||||
int wcharIsAscii(wchar_t *);
|
||||
@@ -92,7 +90,6 @@ struct Object
|
||||
virtual void print();
|
||||
|
||||
virtual char *toChars();
|
||||
virtual dchar *toDchars();
|
||||
virtual void toBuffer(OutBuffer *buf);
|
||||
|
||||
/**
|
||||
@@ -282,14 +279,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);
|
||||
@@ -300,10 +294,6 @@ struct OutBuffer : Object
|
||||
void align(unsigned size);
|
||||
void vprintf(const char *format, va_list args);
|
||||
void printf(const char *format, ...);
|
||||
#if M_UNICODE
|
||||
void vprintf(const unsigned short *format, va_list args);
|
||||
void printf(const unsigned short *format, ...);
|
||||
#endif
|
||||
void bracket(char left, char right);
|
||||
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
|
||||
void spread(unsigned offset, unsigned nbytes);
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
|
||||
// Copyright (c) 2010-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
|
||||
// Copyright (c) 2010-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
typedef void *(fp_speller_t)(void *, const char *);
|
||||
|
||||
extern const char idchars[];
|
||||
|
||||
+71
-21
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+32
-9
@@ -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
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h> // strlen()
|
||||
|
||||
#include "root.h"
|
||||
#include "speller.h"
|
||||
|
||||
+2
-2
@@ -87,7 +87,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
|
||||
@@ -102,7 +102,7 @@ struct Scope
|
||||
#define SCOPEstaticassert 8 // inside static assert
|
||||
#define SCOPEdebug 0x10 // inside debug conditional
|
||||
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
Expressions *attributes; // GCC decl/type attributes
|
||||
#endif
|
||||
|
||||
|
||||
+179
-69
@@ -28,6 +28,7 @@
|
||||
#include "parse.h"
|
||||
#include "template.h"
|
||||
#include "attrib.h"
|
||||
#include "import.h"
|
||||
|
||||
#if IN_LLVM
|
||||
#if defined(_MSC_VER)
|
||||
@@ -426,7 +427,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();
|
||||
@@ -1585,6 +1586,10 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
return s;
|
||||
}
|
||||
|
||||
Type *argtype = (*arguments)[dim-1]->type;
|
||||
if (argtype)
|
||||
argtype = argtype->semantic(loc, sc);
|
||||
|
||||
TypeTuple *tuple = (TypeTuple *)tab;
|
||||
Statements *statements = new Statements();
|
||||
//printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
|
||||
@@ -1599,9 +1604,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
((DotVarExp *)(*te->exps)[0])->e1->isTemp())
|
||||
{
|
||||
CommaExp *ce = (CommaExp *)((DotVarExp *)(*te->exps)[0])->e1;
|
||||
|
||||
prelude = ce->e1;
|
||||
((DotVarExp *)(*te->exps)[0])->e1 = ce->e2;
|
||||
prelude = ce->e1;
|
||||
((DotVarExp *)(*te->exps)[0])->e1 = ce->e2;
|
||||
}
|
||||
}
|
||||
else if (aggr->op == TOKtype) // type tuple
|
||||
@@ -1612,8 +1616,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
assert(0);
|
||||
for (size_t j = 0; j < n; j++)
|
||||
{ size_t k = (op == TOKforeach) ? j : n - 1 - j;
|
||||
Expression *e;
|
||||
Type *t;
|
||||
Expression *e = NULL;
|
||||
Type *t = NULL;
|
||||
if (te)
|
||||
e = (*te->exps)[k];
|
||||
else
|
||||
@@ -1664,14 +1668,20 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
var = new AliasDeclaration(loc, arg->ident, s);
|
||||
if (arg->storageClass & STCref)
|
||||
error("symbol %s cannot be ref", s->toChars());
|
||||
if (argtype && argtype->ty != Terror)
|
||||
error("cannot specify element type for symbol %s", s->toChars());
|
||||
}
|
||||
else if (e->op == TOKtype)
|
||||
{
|
||||
var = new AliasDeclaration(loc, arg->ident, e->type);
|
||||
if (argtype && argtype->ty != Terror)
|
||||
error("cannot specify element type for type %s", e->type->toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
arg->type = e->type;
|
||||
if (argtype && argtype->ty != Terror)
|
||||
arg->type = argtype;
|
||||
Initializer *ie = new ExpInitializer(0, e);
|
||||
VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
|
||||
if (arg->storageClass & STCref)
|
||||
@@ -1688,6 +1698,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
else
|
||||
{
|
||||
var = new AliasDeclaration(loc, arg->ident, t);
|
||||
if (argtype && argtype->ty != Terror)
|
||||
error("cannot specify element type for symbol %s", s->toChars());
|
||||
}
|
||||
DeclarationExp *de = new DeclarationExp(loc, var);
|
||||
st->push(new ExpStatement(loc, de));
|
||||
@@ -1757,23 +1769,47 @@ Lagain:
|
||||
Type *argtype = arg->type->semantic(loc, sc);
|
||||
VarDeclaration *var;
|
||||
|
||||
var = new VarDeclaration(loc, argtype, arg->ident, NULL);
|
||||
var->storage_class |= STCforeach;
|
||||
var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
|
||||
if (var->storage_class & (STCref | STCout))
|
||||
var->storage_class |= STCnodtor;
|
||||
if (dim == 2 && i == 0)
|
||||
{ key = var;
|
||||
//var->storage_class |= STCfinal;
|
||||
{
|
||||
#if (BUG6652 == 1 || BUG6652 == 2)
|
||||
var = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), NULL);
|
||||
var->storage_class |= arg->storageClass & (STCin | STCout | STC_TYPECTOR);
|
||||
#else
|
||||
if (arg->storageClass & STCref)
|
||||
var = new VarDeclaration(loc, argtype, arg->ident, NULL);
|
||||
else
|
||||
var = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), NULL);
|
||||
var->storage_class |= arg->storageClass & (STCin | STCout | STC_TYPECTOR);
|
||||
#endif
|
||||
var->storage_class |= STCforeach;
|
||||
if (var->storage_class & (STCref | STCout))
|
||||
var->storage_class |= STCnodtor;
|
||||
|
||||
key = var;
|
||||
}
|
||||
else
|
||||
{
|
||||
var = new VarDeclaration(loc, argtype, arg->ident, NULL);
|
||||
var->storage_class |= STCforeach;
|
||||
var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
|
||||
if (var->storage_class & (STCref | STCout))
|
||||
var->storage_class |= STCnodtor;
|
||||
|
||||
value = var;
|
||||
/* Reference to immutable data should be marked as const
|
||||
*/
|
||||
if (var->storage_class & STCref && !tn->isMutable())
|
||||
if (var->storage_class & STCref)
|
||||
{
|
||||
var->storage_class |= STCconst;
|
||||
/* Reference to immutable data should be marked as const
|
||||
*/
|
||||
if (!tn->isMutable())
|
||||
var->storage_class |= STCconst;
|
||||
|
||||
Type *t = tab->nextOf();
|
||||
if (!t->invariantOf()->equals(argtype->invariantOf()) ||
|
||||
!MODimplicitConv(t->mod, argtype->mod))
|
||||
{
|
||||
error("argument type mismatch, %s to ref %s",
|
||||
t->toChars(), argtype->toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
@@ -1831,6 +1867,30 @@ Lagain:
|
||||
value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
|
||||
Statement *ds = new ExpStatement(loc, value);
|
||||
|
||||
if (dim == 2)
|
||||
{ Parameter *arg = (*arguments)[0];
|
||||
#if (BUG6652 == 1 || BUG6652 == 2)
|
||||
if ((*arguments)[0]->storageClass & STCref)
|
||||
{
|
||||
AliasDeclaration *v = new AliasDeclaration(loc, arg->ident, key);
|
||||
body = new CompoundStatement(loc, new ExpStatement(loc, v), body);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident));
|
||||
VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie);
|
||||
v->storage_class |= STCforeach | STCref | STCbug6652;
|
||||
body = new CompoundStatement(loc, new ExpStatement(loc, v), body);
|
||||
}
|
||||
#else
|
||||
if (!(arg->storageClass & STCref))
|
||||
{
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident));
|
||||
VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie);
|
||||
body = new CompoundStatement(loc, new ExpStatement(loc, v), body);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
body = new CompoundStatement(loc, ds, body);
|
||||
|
||||
s = new ForStatement(loc, forinit, cond, increment, body);
|
||||
@@ -1901,29 +1961,29 @@ Lagain:
|
||||
goto Lapply;
|
||||
|
||||
{ /* Look for range iteration, i.e. the properties
|
||||
* .empty, .next, .retreat, .head and .rear
|
||||
* .empty, .popFront, .popBack, .front and .back
|
||||
* foreach (e; aggr) { ... }
|
||||
* translates to:
|
||||
* for (auto __r = aggr[]; !__r.empty; __r.next)
|
||||
* { auto e = __r.head;
|
||||
* for (auto __r = aggr[]; !__r.empty; __r.popFront)
|
||||
* { auto e = __r.front;
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
AggregateDeclaration *ad = (tab->ty == Tclass)
|
||||
? (AggregateDeclaration *)((TypeClass *)tab)->sym
|
||||
: (AggregateDeclaration *)((TypeStruct *)tab)->sym;
|
||||
Identifier *idhead;
|
||||
Identifier *idnext;
|
||||
Identifier *idfront;
|
||||
Identifier *idpopFront;
|
||||
if (op == TOKforeach)
|
||||
{ idhead = Id::Ffront;
|
||||
idnext = Id::FpopFront;
|
||||
{ idfront = Id::Ffront;
|
||||
idpopFront = Id::FpopFront;
|
||||
}
|
||||
else
|
||||
{ idhead = Id::Fback;
|
||||
idnext = Id::FpopBack;
|
||||
{ idfront = Id::Fback;
|
||||
idpopFront = Id::FpopBack;
|
||||
}
|
||||
Dsymbol *shead = search_function(ad, idhead);
|
||||
if (!shead)
|
||||
Dsymbol *sfront = ad->search(0, idfront, 0);
|
||||
if (!sfront)
|
||||
goto Lapply;
|
||||
|
||||
/* Generate a temporary __r and initialize it with the aggregate.
|
||||
@@ -1939,13 +1999,13 @@ Lagain:
|
||||
|
||||
// __r.next
|
||||
e = new VarExp(loc, r);
|
||||
Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idnext));
|
||||
Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idpopFront));
|
||||
|
||||
/* Declaration statement for e:
|
||||
* auto e = __r.idhead;
|
||||
* auto e = __r.idfront;
|
||||
*/
|
||||
e = new VarExp(loc, r);
|
||||
Expression *einit = new DotIdExp(loc, e, idhead);
|
||||
Expression *einit = new DotIdExp(loc, e, idfront);
|
||||
Statement *makeargs, *forbody;
|
||||
if (dim == 1)
|
||||
{
|
||||
@@ -1968,7 +2028,7 @@ Lagain:
|
||||
makeargs = new ExpStatement(loc, de);
|
||||
|
||||
Expression *ve = new VarExp(loc, vd);
|
||||
ve->type = shead->isDeclaration()->type;
|
||||
ve->type = sfront->isDeclaration()->type;
|
||||
if (ve->type->toBasetype()->ty == Tfunction)
|
||||
ve->type = ve->type->toBasetype()->nextOf();
|
||||
if (!ve->type || ve->type->ty == Terror)
|
||||
@@ -2046,18 +2106,6 @@ Lagain:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
TypeFunction *tfld = NULL;
|
||||
if (sapply)
|
||||
{ FuncDeclaration *fdapply = sapply->isFuncDeclaration();
|
||||
@@ -2533,7 +2581,14 @@ Statement *ForeachRangeStatement::semantic(Scope *sc)
|
||||
*/
|
||||
|
||||
ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr);
|
||||
key = new VarDeclaration(loc, arg->type, arg->ident, ie);
|
||||
#if (BUG6652 == 1 || BUG6652 == 2)
|
||||
key = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), ie);
|
||||
#else
|
||||
if (arg->storageClass & STCref)
|
||||
key = new VarDeclaration(loc, arg->type, arg->ident, ie);
|
||||
else
|
||||
key = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), ie);
|
||||
#endif
|
||||
|
||||
Identifier *id = Lexer::uniqueId("__limit");
|
||||
ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr);
|
||||
@@ -2580,6 +2635,28 @@ Statement *ForeachRangeStatement::semantic(Scope *sc)
|
||||
//increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
|
||||
increment = new PreExp(TOKpreplusplus, loc, new VarExp(loc, key));
|
||||
|
||||
#if (BUG6652 == 1 || BUG6652 == 2)
|
||||
if (arg->storageClass & STCref)
|
||||
{
|
||||
AliasDeclaration *v = new AliasDeclaration(loc, arg->ident, key);
|
||||
body = new CompoundStatement(loc, new ExpStatement(loc, v), body);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident));
|
||||
VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie);
|
||||
v->storage_class |= STCforeach | STCref | STCbug6652;
|
||||
body = new CompoundStatement(loc, new ExpStatement(loc, v), body);
|
||||
}
|
||||
#else
|
||||
if (!(arg->storageClass & STCref))
|
||||
{
|
||||
ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident));
|
||||
VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie);
|
||||
body = new CompoundStatement(loc, new ExpStatement(loc, v), body);
|
||||
}
|
||||
#endif
|
||||
|
||||
ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
|
||||
s = fs->semantic(sc);
|
||||
return s;
|
||||
@@ -2971,8 +3048,8 @@ Statement *PragmaStatement::semantic(Scope *sc)
|
||||
Expression *e = (*args)[i];
|
||||
|
||||
e = e->semantic(sc);
|
||||
if (e->op != TOKerror)
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->op != TOKerror && e->op != TOKtype)
|
||||
e = e->ctfeInterpret();
|
||||
if (e->op == TOKerror)
|
||||
{ errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
|
||||
goto Lerror;
|
||||
@@ -3002,7 +3079,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)
|
||||
@@ -3033,7 +3110,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())
|
||||
@@ -3171,6 +3248,10 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
||||
|
||||
condition = condition->semantic(sc);
|
||||
condition = resolveProperties(sc, condition);
|
||||
TypeEnum *te = NULL;
|
||||
// preserve enum type for final switches
|
||||
if (condition->type->ty == Tenum)
|
||||
te = (TypeEnum *)condition->type;
|
||||
if (condition->type->isString())
|
||||
{
|
||||
// If it's not an array, cast it to one
|
||||
@@ -3235,8 +3316,8 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
||||
{ // Don't use toBasetype() because that will skip past enums
|
||||
t = ((TypeTypedef *)t)->sym->basetype;
|
||||
}
|
||||
if (condition->type->ty == Tenum)
|
||||
{ TypeEnum *te = (TypeEnum *)condition->type;
|
||||
if (te)
|
||||
{
|
||||
EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration();
|
||||
assert(ed);
|
||||
size_t dim = ed->members->dim;
|
||||
@@ -3247,7 +3328,7 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t j = 0; j < cases->dim; j++)
|
||||
{ CaseStatement *cs = (*cases)[j];
|
||||
if (cs->exp->equals(em->value))
|
||||
if (cs->exp->equals(em->value) || cs->exp->toInteger() == em->value->toInteger())
|
||||
goto L1;
|
||||
}
|
||||
error("enum member %s not represented in final switch", em->toChars());
|
||||
@@ -3397,7 +3478,7 @@ Statement *CaseStatement::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
else
|
||||
exp = exp->optimize(WANTvalue | WANTinterpret);
|
||||
exp = exp->ctfeInterpret();
|
||||
|
||||
if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror)
|
||||
{
|
||||
@@ -3503,12 +3584,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;
|
||||
@@ -3574,12 +3654,12 @@ DefaultStatement::DefaultStatement(Loc loc, Statement *s)
|
||||
: Statement(loc)
|
||||
{
|
||||
this->statement = s;
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
cblock = NULL;
|
||||
#endif
|
||||
#elif IN_LLVM
|
||||
bodyBB = NULL;
|
||||
// LDC
|
||||
enclosingScopeExit = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
Statement *DefaultStatement::syntaxCopy()
|
||||
@@ -3749,6 +3829,7 @@ ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
|
||||
: Statement(loc)
|
||||
{
|
||||
this->exp = exp;
|
||||
this->implicit0 = 0;
|
||||
}
|
||||
|
||||
Statement *ReturnStatement::syntaxCopy()
|
||||
@@ -3766,7 +3847,6 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
|
||||
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
|
||||
Scope *scx = sc;
|
||||
int implicit0 = 0;
|
||||
Expression *eorg = NULL;
|
||||
|
||||
if (fd->fes)
|
||||
@@ -3810,8 +3890,11 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
{
|
||||
fd->hasReturnExp |= 1;
|
||||
|
||||
FuncLiteralDeclaration *fld = fd->isFuncLiteralDeclaration();
|
||||
if (tret)
|
||||
exp = exp->inferType(tbret);
|
||||
else if (fld && fld->treq && fld->treq->nextOf())
|
||||
exp = exp->inferType(fld->treq->nextOf());
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
if (!((TypeFunction *)fd->type)->isref)
|
||||
@@ -3984,11 +4067,14 @@ 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->storage_class |= STCresult;
|
||||
v->semantic(scx);
|
||||
if (!scx->insert(v))
|
||||
if (((TypeFunction *)fd->type)->isref)
|
||||
v->storage_class |= STCref | STCforeach;
|
||||
v->semantic(sco);
|
||||
if (!sco->insert(v))
|
||||
assert(0);
|
||||
v->parent = fd;
|
||||
fd->vresult = v;
|
||||
@@ -4027,7 +4113,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);
|
||||
@@ -4357,9 +4443,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);
|
||||
}
|
||||
@@ -5313,9 +5406,6 @@ LabelDsymbol::LabelDsymbol(Identifier *ident)
|
||||
: Dsymbol(ident)
|
||||
{
|
||||
statement = NULL;
|
||||
#if IN_GCC
|
||||
asmLabelNum = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
|
||||
@@ -5410,9 +5500,29 @@ Statement *ImportStatement::syntaxCopy()
|
||||
Statement *ImportStatement::semantic(Scope *sc)
|
||||
{
|
||||
for (size_t i = 0; i < imports->dim; i++)
|
||||
{ Dsymbol *s = (*imports)[i];
|
||||
{ Import *s = (*imports)[i]->isImport();
|
||||
|
||||
for (size_t i = 0; i < s->names.dim; i++)
|
||||
{
|
||||
Identifier *name = s->names[i];
|
||||
Identifier *alias = s->aliases[i];
|
||||
|
||||
if (!alias)
|
||||
alias = name;
|
||||
|
||||
TypeIdentifier *tname = new TypeIdentifier(s->loc, name);
|
||||
AliasDeclaration *ad = new AliasDeclaration(s->loc, alias, tname);
|
||||
|
||||
s->aliasdecls.push(ad);
|
||||
}
|
||||
|
||||
s->semantic(sc);
|
||||
sc->insert(s);
|
||||
|
||||
for (size_t i = 0; i < s->aliasdecls.dim; i++)
|
||||
{
|
||||
sc->insert(s->aliasdecls[i]);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
+3
-5
@@ -79,7 +79,7 @@ struct DValue;
|
||||
typedef DValue elem;
|
||||
#endif
|
||||
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node block;
|
||||
//union tree_node; typedef union tree_node elem;
|
||||
#else
|
||||
@@ -595,7 +595,7 @@ struct CaseRangeStatement : Statement
|
||||
struct DefaultStatement : Statement
|
||||
{
|
||||
Statement *statement;
|
||||
#if IN_GCC
|
||||
#ifdef IN_GCC
|
||||
block *cblock; // back end: label for the block
|
||||
#endif
|
||||
|
||||
@@ -664,6 +664,7 @@ struct SwitchErrorStatement : Statement
|
||||
struct ReturnStatement : Statement
|
||||
{
|
||||
Expression *exp;
|
||||
int implicit0;
|
||||
|
||||
ReturnStatement(Loc loc, Expression *exp);
|
||||
Statement *syntaxCopy();
|
||||
@@ -930,9 +931,6 @@ struct LabelStatement : Statement
|
||||
struct LabelDsymbol : Dsymbol
|
||||
{
|
||||
LabelStatement *statement;
|
||||
#if IN_GCC
|
||||
unsigned asmLabelNum; // GCC-specific
|
||||
#endif
|
||||
|
||||
LabelDsymbol(Identifier *ident);
|
||||
LabelDsymbol *isLabel();
|
||||
|
||||
+8
-4
@@ -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
|
||||
@@ -59,10 +59,14 @@ void StaticAssert::semantic2(Scope *sc)
|
||||
++sc->ignoreTemplates;
|
||||
Expression *e = exp->semantic(sc);
|
||||
sc = sc->pop();
|
||||
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());
|
||||
@@ -74,7 +78,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());
|
||||
|
||||
+130
-30
@@ -37,7 +37,6 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
scope = 0;
|
||||
structsize = 0; // size of struct
|
||||
alignsize = 0; // size of struct for alignment purposes
|
||||
structalign = 0; // struct member alignment in effect
|
||||
hasUnions = 0;
|
||||
sizeok = SIZEOKnone; // size not determined yet
|
||||
deferred = NULL;
|
||||
@@ -60,6 +59,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
noDefaultCtor = FALSE;
|
||||
#endif
|
||||
dtor = NULL;
|
||||
getRTInfo = NULL;
|
||||
|
||||
#if IN_LLVM
|
||||
availableExternally = true; // assume this unless proven otherwise
|
||||
@@ -83,7 +83,7 @@ void AggregateDeclaration::semantic2(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->semantic2(sc);
|
||||
}
|
||||
sc->pop();
|
||||
@@ -103,10 +103,25 @@ 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();
|
||||
|
||||
if (!getRTInfo)
|
||||
{ // Evaluate: gcinfo!type
|
||||
Objects *tiargs = new Objects();
|
||||
tiargs->push(type);
|
||||
TemplateInstance *ti = new TemplateInstance(loc, Type::rtinfo, tiargs);
|
||||
ti->semantic(sc);
|
||||
ti->semantic2(sc);
|
||||
ti->semantic3(sc);
|
||||
Dsymbol *s = ti->toAlias();
|
||||
Expression *e = new DsymbolExp(0, s, 0);
|
||||
e = e->semantic(ti->tempdecl->scope);
|
||||
e = e->ctfeInterpret();
|
||||
getRTInfo = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +132,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();
|
||||
}
|
||||
@@ -127,6 +142,8 @@ void AggregateDeclaration::inlineScan()
|
||||
unsigned AggregateDeclaration::size(Loc loc)
|
||||
{
|
||||
//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)
|
||||
@@ -196,20 +213,33 @@ int AggregateDeclaration::isExport()
|
||||
*/
|
||||
|
||||
void AggregateDeclaration::alignmember(
|
||||
unsigned salign, // struct alignment that is in effect
|
||||
unsigned size, // alignment requirement of field
|
||||
structalign_t alignment, // struct alignment that is in effect
|
||||
unsigned size, // alignment requirement of field
|
||||
unsigned *poffset)
|
||||
{
|
||||
//printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
|
||||
if (salign > 1)
|
||||
//printf("alignment = %d, size = %d, offset = %d\n",alignment,size,offset);
|
||||
switch (alignment)
|
||||
{
|
||||
assert(size != 3);
|
||||
unsigned sa = size;
|
||||
if (sa == 0 || salign < sa)
|
||||
sa = salign;
|
||||
*poffset = (*poffset + sa - 1) & ~(sa - 1);
|
||||
case 1:
|
||||
// No alignment
|
||||
break;
|
||||
|
||||
case STRUCTALIGN_DEFAULT:
|
||||
{ /* Must match what the corresponding C compiler's default
|
||||
* alignment behavior is.
|
||||
*/
|
||||
assert(size != 3);
|
||||
unsigned sa = (size == 0 || 8 < size) ? 8 : size;
|
||||
*poffset = (*poffset + sa - 1) & ~(sa - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Align on alignment boundary, which must be a positive power of 2
|
||||
assert(alignment > 0 && !(alignment & (alignment - 1)));
|
||||
*poffset = (*poffset + alignment - 1) & ~(alignment - 1);
|
||||
break;
|
||||
}
|
||||
//printf("result = %d\n",offset);
|
||||
}
|
||||
|
||||
/****************************************
|
||||
@@ -221,25 +251,36 @@ 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 alignment, // 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
|
||||
)
|
||||
{
|
||||
unsigned ofs = *nextoffset;
|
||||
alignmember(memalign, memalignsize, &ofs);
|
||||
alignmember(alignment, memalignsize, &ofs);
|
||||
unsigned memoffset = ofs;
|
||||
ofs += memsize;
|
||||
if (ofs > *paggsize)
|
||||
*paggsize = ofs;
|
||||
if (!isunion)
|
||||
*nextoffset = ofs;
|
||||
if (global.params.is64bit && memalign == 8 && memalignsize == 16)
|
||||
/* Not sure how to handle this */
|
||||
;
|
||||
else if (memalign < memalignsize)
|
||||
memalignsize = memalign;
|
||||
|
||||
if (alignment == STRUCTALIGN_DEFAULT)
|
||||
{
|
||||
if (global.params.is64bit && memalignsize == 16)
|
||||
;
|
||||
else if (8 < memalignsize)
|
||||
memalignsize = 8;
|
||||
else if (alignment < memalignsize)
|
||||
memalignsize = alignment;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (memalignsize < alignment)
|
||||
memalignsize = alignment;
|
||||
}
|
||||
|
||||
if (*paggalignsize < memalignsize)
|
||||
*paggalignsize = memalignsize;
|
||||
|
||||
@@ -265,13 +306,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;
|
||||
@@ -290,7 +331,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.
|
||||
*/
|
||||
@@ -300,7 +341,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;
|
||||
@@ -322,7 +363,10 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
||||
postblit = NULL;
|
||||
|
||||
xeq = NULL;
|
||||
alignment = 0;
|
||||
#endif
|
||||
arg1type = NULL;
|
||||
arg2type = NULL;
|
||||
|
||||
// For forward references
|
||||
type = new TypeStruct(this);
|
||||
@@ -389,8 +433,8 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
#else
|
||||
handle = type->pointerTo();
|
||||
#endif
|
||||
structalign = sc->structalign;
|
||||
protection = sc->protection;
|
||||
alignment = sc->structalign;
|
||||
storage_class |= sc->stc;
|
||||
if (sc->stc & STCdeprecated)
|
||||
isdeprecated = true;
|
||||
@@ -403,7 +447,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
int hasfunctions = 0;
|
||||
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);
|
||||
if (s->isFuncDeclaration())
|
||||
@@ -452,6 +496,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
sc2->inunion = 1;
|
||||
sc2->protection = PROTpublic;
|
||||
sc2->explicitProtection = 0;
|
||||
sc2->structalign = STRUCTALIGN_DEFAULT;
|
||||
|
||||
size_t members_dim = members->dim;
|
||||
|
||||
@@ -507,7 +552,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
fields.setDim(0);
|
||||
structsize = 0;
|
||||
alignsize = 0;
|
||||
structalign = 0;
|
||||
// structalign = 0;
|
||||
|
||||
scope = scx ? scx : new Scope(*sc);
|
||||
scope->setNoFree();
|
||||
@@ -631,6 +676,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);
|
||||
@@ -667,6 +721,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;
|
||||
|
||||
@@ -690,11 +745,56 @@ void StructDeclaration::finalizeSize(Scope *sc)
|
||||
// Round struct size up to next alignsize boundary.
|
||||
// This will ensure that arrays of structs will get their internals
|
||||
// aligned properly.
|
||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||
if (alignment == STRUCTALIGN_DEFAULT)
|
||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||
else
|
||||
structsize = (structsize + alignment - 1) & ~(alignment - 1);
|
||||
|
||||
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()
|
||||
{
|
||||
if (isnested || cpctor || postblit || ctor || dtor)
|
||||
return false;
|
||||
|
||||
/* Recursively check any fields have a constructor.
|
||||
* We should cache the results of this.
|
||||
*/
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->storage_class & STCfield);
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (!sd->isPOD())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->printf("%s ", kind());
|
||||
@@ -711,7 +811,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);
|
||||
|
||||
+429
-259
File diff suppressed because it is too large
Load Diff
+16
-16
@@ -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
|
||||
@@ -89,7 +89,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
|
||||
#define ISTYPE(cond) \
|
||||
for (size_t i = 0; i < dim; i++) \
|
||||
{ Type *t = getType(args->tdata()[i]); \
|
||||
{ Type *t = getType((*args)[i]); \
|
||||
if (!t) \
|
||||
goto Lfalse; \
|
||||
if (!(cond)) \
|
||||
@@ -101,7 +101,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
|
||||
#define ISDSYMBOL(cond) \
|
||||
for (size_t i = 0; i < dim; i++) \
|
||||
{ Dsymbol *s = getDsymbol(args->tdata()[i]); \
|
||||
{ Dsymbol *s = getDsymbol((*args)[i]); \
|
||||
if (!s) \
|
||||
goto Lfalse; \
|
||||
if (!(cond)) \
|
||||
@@ -196,7 +196,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = args->tdata()[0];
|
||||
Object *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
if (!s || !s->ident)
|
||||
{
|
||||
@@ -210,7 +210,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = args->tdata()[0];
|
||||
Object *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
if (s)
|
||||
s = s->toParent();
|
||||
@@ -231,13 +231,13 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 2)
|
||||
goto Ldimerror;
|
||||
Object *o = args->tdata()[0];
|
||||
Expression *e = isExpression(args->tdata()[1]);
|
||||
Object *o = (*args)[0];
|
||||
Expression *e = isExpression((*args)[1]);
|
||||
if (!e)
|
||||
{ error("expression expected as second argument of __traits %s", ident->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
e = e->ctfeInterpret();
|
||||
StringExp *se = e->toString();
|
||||
if (!se || se->length() == 0)
|
||||
{ error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars());
|
||||
@@ -336,7 +336,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = args->tdata()[0];
|
||||
Object *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
ClassDeclaration *cd;
|
||||
if (!s || (cd = s->isClassDeclaration()) == NULL)
|
||||
@@ -350,7 +350,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = args->tdata()[0];
|
||||
Object *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
ScopeDsymbol *sd;
|
||||
if (!s)
|
||||
@@ -380,7 +380,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
/* Skip if already present in idents[]
|
||||
*/
|
||||
for (size_t j = 0; j < idents->dim; j++)
|
||||
{ Identifier *id = idents->tdata()[j];
|
||||
{ Identifier *id = (*idents)[j];
|
||||
if (id == sm->ident)
|
||||
return 0;
|
||||
#ifdef DEBUG
|
||||
@@ -421,9 +421,9 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
assert(sizeof(Expressions) == sizeof(Identifiers));
|
||||
Expressions *exps = (Expressions *)idents;
|
||||
for (size_t i = 0; i < idents->dim; i++)
|
||||
{ Identifier *id = idents->tdata()[i];
|
||||
{ Identifier *id = (*idents)[i];
|
||||
StringExp *se = new StringExp(loc, id->toChars());
|
||||
exps->tdata()[i] = se;
|
||||
(*exps)[i] = se;
|
||||
}
|
||||
|
||||
#if DMDV1
|
||||
@@ -448,7 +448,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
goto Lfalse;
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ Object *o = args->tdata()[i];
|
||||
{ Object *o = (*args)[i];
|
||||
Expression *e;
|
||||
|
||||
unsigned errors = global.startGagging();
|
||||
@@ -491,8 +491,8 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
if (dim != 2)
|
||||
goto Ldimerror;
|
||||
TemplateInstance::semanticTiargs(loc, sc, args, 0);
|
||||
Object *o1 = args->tdata()[0];
|
||||
Object *o2 = args->tdata()[1];
|
||||
Object *o1 = (*args)[0];
|
||||
Object *o2 = (*args)[1];
|
||||
Dsymbol *s1 = getDsymbol(o1);
|
||||
Dsymbol *s2 = getDsymbol(o2);
|
||||
|
||||
|
||||
-323
@@ -1,323 +0,0 @@
|
||||
|
||||
// Copyright (c) 2003 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*******************************
|
||||
* Return !=0 if unicode alpha.
|
||||
* Use table from C99 Appendix D.
|
||||
*/
|
||||
|
||||
int isUniAlpha(unsigned u)
|
||||
{
|
||||
static unsigned short table[][2] =
|
||||
{
|
||||
{ 0x00AA, 0x00AA },
|
||||
{ 0x00B5, 0x00B5 },
|
||||
{ 0x00B7, 0x00B7 },
|
||||
{ 0x00BA, 0x00BA },
|
||||
{ 0x00C0, 0x00D6 },
|
||||
{ 0x00D8, 0x00F6 },
|
||||
{ 0x00F8, 0x01F5 },
|
||||
{ 0x01FA, 0x0217 },
|
||||
{ 0x0250, 0x02A8 },
|
||||
{ 0x02B0, 0x02B8 },
|
||||
{ 0x02BB, 0x02BB },
|
||||
{ 0x02BD, 0x02C1 },
|
||||
{ 0x02D0, 0x02D1 },
|
||||
{ 0x02E0, 0x02E4 },
|
||||
{ 0x037A, 0x037A },
|
||||
{ 0x0386, 0x0386 },
|
||||
{ 0x0388, 0x038A },
|
||||
{ 0x038C, 0x038C },
|
||||
{ 0x038E, 0x03A1 },
|
||||
{ 0x03A3, 0x03CE },
|
||||
{ 0x03D0, 0x03D6 },
|
||||
{ 0x03DA, 0x03DA },
|
||||
{ 0x03DC, 0x03DC },
|
||||
{ 0x03DE, 0x03DE },
|
||||
{ 0x03E0, 0x03E0 },
|
||||
{ 0x03E2, 0x03F3 },
|
||||
{ 0x0401, 0x040C },
|
||||
{ 0x040E, 0x044F },
|
||||
{ 0x0451, 0x045C },
|
||||
{ 0x045E, 0x0481 },
|
||||
{ 0x0490, 0x04C4 },
|
||||
{ 0x04C7, 0x04C8 },
|
||||
{ 0x04CB, 0x04CC },
|
||||
{ 0x04D0, 0x04EB },
|
||||
{ 0x04EE, 0x04F5 },
|
||||
{ 0x04F8, 0x04F9 },
|
||||
{ 0x0531, 0x0556 },
|
||||
{ 0x0559, 0x0559 },
|
||||
{ 0x0561, 0x0587 },
|
||||
{ 0x05B0, 0x05B9 },
|
||||
{ 0x05BB, 0x05BD },
|
||||
{ 0x05BF, 0x05BF },
|
||||
{ 0x05C1, 0x05C2 },
|
||||
{ 0x05D0, 0x05EA },
|
||||
{ 0x05F0, 0x05F2 },
|
||||
{ 0x0621, 0x063A },
|
||||
{ 0x0640, 0x0652 },
|
||||
{ 0x0660, 0x0669 },
|
||||
{ 0x0670, 0x06B7 },
|
||||
{ 0x06BA, 0x06BE },
|
||||
{ 0x06C0, 0x06CE },
|
||||
{ 0x06D0, 0x06DC },
|
||||
{ 0x06E5, 0x06E8 },
|
||||
{ 0x06EA, 0x06ED },
|
||||
{ 0x06F0, 0x06F9 },
|
||||
{ 0x0901, 0x0903 },
|
||||
{ 0x0905, 0x0939 },
|
||||
{ 0x093D, 0x093D },
|
||||
{ 0x093E, 0x094D },
|
||||
{ 0x0950, 0x0952 },
|
||||
{ 0x0958, 0x0963 },
|
||||
{ 0x0966, 0x096F },
|
||||
{ 0x0981, 0x0983 },
|
||||
{ 0x0985, 0x098C },
|
||||
{ 0x098F, 0x0990 },
|
||||
{ 0x0993, 0x09A8 },
|
||||
{ 0x09AA, 0x09B0 },
|
||||
{ 0x09B2, 0x09B2 },
|
||||
{ 0x09B6, 0x09B9 },
|
||||
{ 0x09BE, 0x09C4 },
|
||||
{ 0x09C7, 0x09C8 },
|
||||
{ 0x09CB, 0x09CD },
|
||||
{ 0x09DC, 0x09DD },
|
||||
{ 0x09DF, 0x09E3 },
|
||||
{ 0x09E6, 0x09EF },
|
||||
{ 0x09F0, 0x09F1 },
|
||||
{ 0x0A02, 0x0A02 },
|
||||
{ 0x0A05, 0x0A0A },
|
||||
{ 0x0A0F, 0x0A10 },
|
||||
{ 0x0A13, 0x0A28 },
|
||||
{ 0x0A2A, 0x0A30 },
|
||||
{ 0x0A32, 0x0A33 },
|
||||
{ 0x0A35, 0x0A36 },
|
||||
{ 0x0A38, 0x0A39 },
|
||||
{ 0x0A3E, 0x0A42 },
|
||||
{ 0x0A47, 0x0A48 },
|
||||
{ 0x0A4B, 0x0A4D },
|
||||
{ 0x0A59, 0x0A5C },
|
||||
{ 0x0A5E, 0x0A5E },
|
||||
{ 0x0A66, 0x0A6F },
|
||||
{ 0x0A74, 0x0A74 },
|
||||
{ 0x0A81, 0x0A83 },
|
||||
{ 0x0A85, 0x0A8B },
|
||||
{ 0x0A8D, 0x0A8D },
|
||||
{ 0x0A8F, 0x0A91 },
|
||||
{ 0x0A93, 0x0AA8 },
|
||||
{ 0x0AAA, 0x0AB0 },
|
||||
{ 0x0AB2, 0x0AB3 },
|
||||
{ 0x0AB5, 0x0AB9 },
|
||||
{ 0x0ABD, 0x0AC5 },
|
||||
{ 0x0AC7, 0x0AC9 },
|
||||
{ 0x0ACB, 0x0ACD },
|
||||
{ 0x0AD0, 0x0AD0 },
|
||||
{ 0x0AE0, 0x0AE0 },
|
||||
{ 0x0AE6, 0x0AEF },
|
||||
{ 0x0B01, 0x0B03 },
|
||||
{ 0x0B05, 0x0B0C },
|
||||
{ 0x0B0F, 0x0B10 },
|
||||
{ 0x0B13, 0x0B28 },
|
||||
{ 0x0B2A, 0x0B30 },
|
||||
{ 0x0B32, 0x0B33 },
|
||||
{ 0x0B36, 0x0B39 },
|
||||
{ 0x0B3D, 0x0B3D },
|
||||
{ 0x0B3E, 0x0B43 },
|
||||
{ 0x0B47, 0x0B48 },
|
||||
{ 0x0B4B, 0x0B4D },
|
||||
{ 0x0B5C, 0x0B5D },
|
||||
{ 0x0B5F, 0x0B61 },
|
||||
{ 0x0B66, 0x0B6F },
|
||||
{ 0x0B82, 0x0B83 },
|
||||
{ 0x0B85, 0x0B8A },
|
||||
{ 0x0B8E, 0x0B90 },
|
||||
{ 0x0B92, 0x0B95 },
|
||||
{ 0x0B99, 0x0B9A },
|
||||
{ 0x0B9C, 0x0B9C },
|
||||
{ 0x0B9E, 0x0B9F },
|
||||
{ 0x0BA3, 0x0BA4 },
|
||||
{ 0x0BA8, 0x0BAA },
|
||||
{ 0x0BAE, 0x0BB5 },
|
||||
{ 0x0BB7, 0x0BB9 },
|
||||
{ 0x0BBE, 0x0BC2 },
|
||||
{ 0x0BC6, 0x0BC8 },
|
||||
{ 0x0BCA, 0x0BCD },
|
||||
{ 0x0BE7, 0x0BEF },
|
||||
{ 0x0C01, 0x0C03 },
|
||||
{ 0x0C05, 0x0C0C },
|
||||
{ 0x0C0E, 0x0C10 },
|
||||
{ 0x0C12, 0x0C28 },
|
||||
{ 0x0C2A, 0x0C33 },
|
||||
{ 0x0C35, 0x0C39 },
|
||||
{ 0x0C3E, 0x0C44 },
|
||||
{ 0x0C46, 0x0C48 },
|
||||
{ 0x0C4A, 0x0C4D },
|
||||
{ 0x0C60, 0x0C61 },
|
||||
{ 0x0C66, 0x0C6F },
|
||||
{ 0x0C82, 0x0C83 },
|
||||
{ 0x0C85, 0x0C8C },
|
||||
{ 0x0C8E, 0x0C90 },
|
||||
{ 0x0C92, 0x0CA8 },
|
||||
{ 0x0CAA, 0x0CB3 },
|
||||
{ 0x0CB5, 0x0CB9 },
|
||||
{ 0x0CBE, 0x0CC4 },
|
||||
{ 0x0CC6, 0x0CC8 },
|
||||
{ 0x0CCA, 0x0CCD },
|
||||
{ 0x0CDE, 0x0CDE },
|
||||
{ 0x0CE0, 0x0CE1 },
|
||||
{ 0x0CE6, 0x0CEF },
|
||||
{ 0x0D02, 0x0D03 },
|
||||
{ 0x0D05, 0x0D0C },
|
||||
{ 0x0D0E, 0x0D10 },
|
||||
{ 0x0D12, 0x0D28 },
|
||||
{ 0x0D2A, 0x0D39 },
|
||||
{ 0x0D3E, 0x0D43 },
|
||||
{ 0x0D46, 0x0D48 },
|
||||
{ 0x0D4A, 0x0D4D },
|
||||
{ 0x0D60, 0x0D61 },
|
||||
{ 0x0D66, 0x0D6F },
|
||||
{ 0x0E01, 0x0E3A },
|
||||
{ 0x0E40, 0x0E5B },
|
||||
// { 0x0E50, 0x0E59 },
|
||||
{ 0x0E81, 0x0E82 },
|
||||
{ 0x0E84, 0x0E84 },
|
||||
{ 0x0E87, 0x0E88 },
|
||||
{ 0x0E8A, 0x0E8A },
|
||||
{ 0x0E8D, 0x0E8D },
|
||||
{ 0x0E94, 0x0E97 },
|
||||
{ 0x0E99, 0x0E9F },
|
||||
{ 0x0EA1, 0x0EA3 },
|
||||
{ 0x0EA5, 0x0EA5 },
|
||||
{ 0x0EA7, 0x0EA7 },
|
||||
{ 0x0EAA, 0x0EAB },
|
||||
{ 0x0EAD, 0x0EAE },
|
||||
{ 0x0EB0, 0x0EB9 },
|
||||
{ 0x0EBB, 0x0EBD },
|
||||
{ 0x0EC0, 0x0EC4 },
|
||||
{ 0x0EC6, 0x0EC6 },
|
||||
{ 0x0EC8, 0x0ECD },
|
||||
{ 0x0ED0, 0x0ED9 },
|
||||
{ 0x0EDC, 0x0EDD },
|
||||
{ 0x0F00, 0x0F00 },
|
||||
{ 0x0F18, 0x0F19 },
|
||||
{ 0x0F20, 0x0F33 },
|
||||
{ 0x0F35, 0x0F35 },
|
||||
{ 0x0F37, 0x0F37 },
|
||||
{ 0x0F39, 0x0F39 },
|
||||
{ 0x0F3E, 0x0F47 },
|
||||
{ 0x0F49, 0x0F69 },
|
||||
{ 0x0F71, 0x0F84 },
|
||||
{ 0x0F86, 0x0F8B },
|
||||
{ 0x0F90, 0x0F95 },
|
||||
{ 0x0F97, 0x0F97 },
|
||||
{ 0x0F99, 0x0FAD },
|
||||
{ 0x0FB1, 0x0FB7 },
|
||||
{ 0x0FB9, 0x0FB9 },
|
||||
{ 0x10A0, 0x10C5 },
|
||||
{ 0x10D0, 0x10F6 },
|
||||
{ 0x1E00, 0x1E9B },
|
||||
{ 0x1EA0, 0x1EF9 },
|
||||
{ 0x1F00, 0x1F15 },
|
||||
{ 0x1F18, 0x1F1D },
|
||||
{ 0x1F20, 0x1F45 },
|
||||
{ 0x1F48, 0x1F4D },
|
||||
{ 0x1F50, 0x1F57 },
|
||||
{ 0x1F59, 0x1F59 },
|
||||
{ 0x1F5B, 0x1F5B },
|
||||
{ 0x1F5D, 0x1F5D },
|
||||
{ 0x1F5F, 0x1F7D },
|
||||
{ 0x1F80, 0x1FB4 },
|
||||
{ 0x1FB6, 0x1FBC },
|
||||
{ 0x1FBE, 0x1FBE },
|
||||
{ 0x1FC2, 0x1FC4 },
|
||||
{ 0x1FC6, 0x1FCC },
|
||||
{ 0x1FD0, 0x1FD3 },
|
||||
{ 0x1FD6, 0x1FDB },
|
||||
{ 0x1FE0, 0x1FEC },
|
||||
{ 0x1FF2, 0x1FF4 },
|
||||
{ 0x1FF6, 0x1FFC },
|
||||
{ 0x203F, 0x2040 },
|
||||
{ 0x207F, 0x207F },
|
||||
{ 0x2102, 0x2102 },
|
||||
{ 0x2107, 0x2107 },
|
||||
{ 0x210A, 0x2113 },
|
||||
{ 0x2115, 0x2115 },
|
||||
{ 0x2118, 0x211D },
|
||||
{ 0x2124, 0x2124 },
|
||||
{ 0x2126, 0x2126 },
|
||||
{ 0x2128, 0x2128 },
|
||||
{ 0x212A, 0x2131 },
|
||||
{ 0x2133, 0x2138 },
|
||||
{ 0x2160, 0x2182 },
|
||||
{ 0x3005, 0x3007 },
|
||||
{ 0x3021, 0x3029 },
|
||||
{ 0x3041, 0x3093 },
|
||||
{ 0x309B, 0x309C },
|
||||
{ 0x30A1, 0x30F6 },
|
||||
{ 0x30FB, 0x30FC },
|
||||
{ 0x3105, 0x312C },
|
||||
{ 0x4E00, 0x9FA5 },
|
||||
{ 0xAC00, 0xD7A3 },
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
|
||||
{
|
||||
//printf("%x\n", table[i][0]);
|
||||
assert(table[i][0] <= table[i][1]);
|
||||
if (i < sizeof(table) / sizeof(table[0]) - 1)
|
||||
assert(table[i][1] < table[i + 1][0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (u > 0xD7A3)
|
||||
goto Lisnot;
|
||||
|
||||
// Binary search
|
||||
int mid;
|
||||
int low;
|
||||
int high;
|
||||
|
||||
low = 0;
|
||||
high = sizeof(table) / sizeof(table[0]) - 1;
|
||||
while (low <= high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
if (u < table[mid][0])
|
||||
high = mid - 1;
|
||||
else if (u > table[mid][1])
|
||||
low = mid + 1;
|
||||
else
|
||||
goto Lis;
|
||||
}
|
||||
|
||||
Lisnot:
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
|
||||
{
|
||||
assert(u < table[i][0] || u > table[i][1]);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
Lis:
|
||||
#ifdef DEBUG
|
||||
for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++)
|
||||
{
|
||||
if (u >= table[i][0] && u <= table[i][1])
|
||||
return 1;
|
||||
}
|
||||
assert(0); // should have been in table
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
|
||||
// Copyright (c) 2010-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
+228
-237
@@ -1,5 +1,5 @@
|
||||
// utf.c
|
||||
// Copyright (c) 2003-2009 by Digital Mars
|
||||
// Copyright (c) 2003-2012 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -7,22 +7,32 @@
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
// Description of UTF-8 at:
|
||||
// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
/// Description of UTF-8 in [1]. Unicode non-characters and private-use
|
||||
/// code points described in [2],[4].
|
||||
///
|
||||
/// References:
|
||||
/// [1] http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
/// [2] http://en.wikipedia.org/wiki/Unicode
|
||||
/// [3] http://unicode.org/faq/utf_bom.html
|
||||
/// [4] http://www.unicode.org/versions/Unicode6.1.0/ch03.pdf
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "utf.h"
|
||||
|
||||
int utf_isValidDchar(dchar_t c)
|
||||
namespace
|
||||
{
|
||||
return c < 0xD800 ||
|
||||
(c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF);
|
||||
}
|
||||
|
||||
static const unsigned char UTF8stride[256] =
|
||||
/* The following encodings are valid, except for the 5 and 6 byte
|
||||
* combinations:
|
||||
* 0xxxxxxx
|
||||
* 110xxxxx 10xxxxxx
|
||||
* 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
const unsigned UTF8_STRIDE[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,
|
||||
@@ -42,237 +52,73 @@ static const unsigned char UTF8stride[256] =
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
|
||||
};
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-8 sequence starting at index i
|
||||
* in string s.
|
||||
* Returns:
|
||||
* The number of bytes in the UTF-8 sequence or
|
||||
* 0xFF meaning s[i] is not the start of of UTF-8 sequence.
|
||||
*/
|
||||
} // namespace
|
||||
|
||||
unsigned stride(unsigned char* s, size_t i)
|
||||
namespace Unicode
|
||||
{
|
||||
unsigned result = UTF8stride[s[i]];
|
||||
return result;
|
||||
|
||||
// UTF-8 decoding errors
|
||||
char const UTF8_DECODE_OUTSIDE_CODE_SPACE[] = "Outside Unicode code space";
|
||||
char const UTF8_DECODE_TRUNCATED_SEQUENCE[] = "Truncated UTF-8 sequence";
|
||||
char const UTF8_DECODE_OVERLONG[] = "Overlong UTF-8 sequence";
|
||||
char const UTF8_DECODE_INVALID_TRAILER[] = "Invalid trailing code unit";
|
||||
char const UTF8_DECODE_INVALID_CODE_POINT[] = "Invalid code point decoded";
|
||||
|
||||
// UTF-16 decoding errors
|
||||
char const UTF16_DECODE_TRUNCATED_SEQUENCE[]= "Truncated UTF-16 sequence";
|
||||
char const UTF16_DECODE_INVALID_SURROGATE[] = "Invalid low surrogate";
|
||||
char const UTF16_DECODE_UNPAIRED_SURROGATE[]= "Unpaired surrogate";
|
||||
char const UTF16_DECODE_INVALID_CODE_POINT[]= "Invalid code point decoded";
|
||||
|
||||
} // namespace Unicode
|
||||
|
||||
using namespace Unicode;
|
||||
|
||||
/// The Unicode code space is the range of code points [0x000000,0x10FFFF]
|
||||
/// except the UTF-16 surrogate pairs in the range [0xD800,0xDFFF]
|
||||
/// and non-characters (which end in 0xFFFE or 0xFFFF).
|
||||
bool utf_isValidDchar(dchar_t c)
|
||||
{
|
||||
// TODO: Whether non-char code points should be rejected is pending review
|
||||
return c <= 0x10FFFF // largest character code point
|
||||
&& !(0xD800 <= c && c <= 0xDFFF) // surrogate pairs
|
||||
&& (c & 0xFFFFFE) != 0x00FFFE // non-characters
|
||||
// && (c & 0xFFFE) != 0xFFFE // non-characters
|
||||
// && !(0x00FDD0 <= c && c <= 0x00FDEF) // non-characters
|
||||
;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Decode a single UTF-8 character sequence.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
/*******************************
|
||||
* Return !=0 if unicode alpha.
|
||||
* Use table from C99 Appendix D.
|
||||
*/
|
||||
|
||||
const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult)
|
||||
bool isUniAlpha(dchar_t c)
|
||||
{
|
||||
dchar_t V;
|
||||
size_t i = *pidx;
|
||||
unsigned char u = s[i];
|
||||
|
||||
//printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len);
|
||||
|
||||
assert(i >= 0 && i < len);
|
||||
|
||||
if (u & 0x80)
|
||||
{ unsigned n;
|
||||
unsigned char u2;
|
||||
|
||||
/* The following encodings are valid, except for the 5 and 6 byte
|
||||
* combinations:
|
||||
* 0xxxxxxx
|
||||
* 110xxxxx 10xxxxxx
|
||||
* 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
for (n = 1; ; n++)
|
||||
{
|
||||
if (n > 4)
|
||||
goto Lerr; // only do the first 4 of 6 encodings
|
||||
if (((u << n) & 0x80) == 0)
|
||||
{
|
||||
if (n == 1)
|
||||
goto Lerr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pick off (7 - n) significant bits of B from first byte of octet
|
||||
V = (dchar_t)(u & ((1 << (7 - n)) - 1));
|
||||
|
||||
if (i + (n - 1) >= len)
|
||||
goto Lerr; // off end of string
|
||||
|
||||
/* The following combinations are overlong, and illegal:
|
||||
* 1100000x (10xxxxxx)
|
||||
* 11100000 100xxxxx (10xxxxxx)
|
||||
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
|
||||
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
*/
|
||||
u2 = s[i + 1];
|
||||
if ((u & 0xFE) == 0xC0 ||
|
||||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
|
||||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
|
||||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
|
||||
(u == 0xFC && (u2 & 0xFC) == 0x80))
|
||||
goto Lerr; // overlong combination
|
||||
|
||||
for (unsigned j = 1; j != n; j++)
|
||||
{
|
||||
u = s[i + j];
|
||||
if ((u & 0xC0) != 0x80)
|
||||
goto Lerr; // trailing bytes are 10xxxxxx
|
||||
V = (V << 6) | (u & 0x3F);
|
||||
}
|
||||
if (!utf_isValidDchar(V))
|
||||
goto Lerr;
|
||||
i += n;
|
||||
}
|
||||
else
|
||||
static size_t const END = sizeof(ALPHA_TABLE) / sizeof(ALPHA_TABLE[0]);
|
||||
size_t high = END - 1;
|
||||
// Shortcut search if c is out of range
|
||||
size_t low
|
||||
= (c < ALPHA_TABLE[0][0] || ALPHA_TABLE[high][1] < c) ? high + 1 : 0;
|
||||
// Binary search
|
||||
while (low <= high)
|
||||
{
|
||||
V = (dchar_t) u;
|
||||
i++;
|
||||
}
|
||||
|
||||
assert(utf_isValidDchar(V));
|
||||
*pidx = i;
|
||||
*presult = V;
|
||||
return NULL;
|
||||
|
||||
Lerr:
|
||||
*presult = (dchar_t) s[i];
|
||||
*pidx = i + 1;
|
||||
return "invalid UTF-8 sequence";
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
* Validate a UTF-8 string.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
*/
|
||||
|
||||
const char *utf_validateString(unsigned char *s, size_t len)
|
||||
{
|
||||
size_t idx;
|
||||
const char *err = NULL;
|
||||
dchar_t dc;
|
||||
|
||||
for (idx = 0; idx < len; )
|
||||
{
|
||||
err = utf_decodeChar(s, len, &idx, &dc);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Decode a single UTF-16 character sequence.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
*/
|
||||
|
||||
|
||||
const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult)
|
||||
{
|
||||
const char *msg;
|
||||
size_t i = *pidx;
|
||||
unsigned u = s[i];
|
||||
|
||||
assert(i >= 0 && i < len);
|
||||
if (u & ~0x7F)
|
||||
{ if (u >= 0xD800 && u <= 0xDBFF)
|
||||
{ unsigned u2;
|
||||
|
||||
if (i + 1 == len)
|
||||
{ msg = "surrogate UTF-16 high value past end of string";
|
||||
goto Lerr;
|
||||
}
|
||||
u2 = s[i + 1];
|
||||
if (u2 < 0xDC00 || u2 > 0xDFFF)
|
||||
{ msg = "surrogate UTF-16 low value out of range";
|
||||
goto Lerr;
|
||||
}
|
||||
u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
|
||||
i += 2;
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{ msg = "unpaired surrogate UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{ msg = "illegal UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
size_t mid = (low + high) >> 1;
|
||||
if (c < ALPHA_TABLE[mid][0])
|
||||
high = mid - 1;
|
||||
else if (ALPHA_TABLE[mid][1] < c)
|
||||
low = mid + 1;
|
||||
else
|
||||
i++;
|
||||
{
|
||||
assert(ALPHA_TABLE[mid][0] <= c && c <= ALPHA_TABLE[mid][1]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
assert(utf_isValidDchar(u));
|
||||
*pidx = i;
|
||||
*presult = (dchar_t)u;
|
||||
return NULL;
|
||||
|
||||
Lerr:
|
||||
*presult = (dchar_t)s[i];
|
||||
*pidx = i + 1;
|
||||
return msg;
|
||||
return false;
|
||||
}
|
||||
|
||||
void utf_encodeChar(unsigned char *s, dchar_t c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
s[0] = (char) c;
|
||||
}
|
||||
else if (c <= 0x7FF)
|
||||
{
|
||||
s[0] = (char)(0xC0 | (c >> 6));
|
||||
s[1] = (char)(0x80 | (c & 0x3F));
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
s[0] = (char)(0xE0 | (c >> 12));
|
||||
s[1] = (char)(0x80 | ((c >> 6) & 0x3F));
|
||||
s[2] = (char)(0x80 | (c & 0x3F));
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
s[0] = (char)(0xF0 | (c >> 18));
|
||||
s[1] = (char)(0x80 | ((c >> 12) & 0x3F));
|
||||
s[2] = (char)(0x80 | ((c >> 6) & 0x3F));
|
||||
s[3] = (char)(0x80 | (c & 0x3F));
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void utf_encodeWchar(unsigned short *s, dchar_t c)
|
||||
{
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
s[0] = (wchar_t) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
s[0] = (wchar_t) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
s[1] = (wchar_t) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the code length of c in the encoding.
|
||||
* The code is returned in character count, not in bytes.
|
||||
* Returns the code length of c in code units.
|
||||
*/
|
||||
|
||||
int utf_codeLengthChar(dchar_t c)
|
||||
@@ -291,10 +137,10 @@ int utf_codeLengthWchar(dchar_t c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code length of c in the encoding.
|
||||
* Returns the code length of c in code units for the encoding.
|
||||
* sz is the encoding: 1 = utf8, 2 = utf16, 4 = utf32.
|
||||
* The code is returned in character count, not in bytes.
|
||||
*/
|
||||
|
||||
int utf_codeLength(int sz, dchar_t c)
|
||||
{
|
||||
if (sz == 1)
|
||||
@@ -305,16 +151,161 @@ int utf_codeLength(int sz, dchar_t c)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void utf_encode(int sz, void *s, dchar_t c)
|
||||
void utf_encodeChar(utf8_t *s, dchar_t c)
|
||||
{
|
||||
if (sz == 1)
|
||||
utf_encodeChar((unsigned char *)s, c);
|
||||
else if (sz == 2)
|
||||
utf_encodeWchar((unsigned short *)s, c);
|
||||
assert(s != NULL);
|
||||
assert(utf_isValidDchar(c));
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
s[0] = static_cast<utf8_t>(c);
|
||||
}
|
||||
else if (c <= 0x07FF)
|
||||
{
|
||||
s[0] = static_cast<utf8_t>(0xC0 | (c >> 6));
|
||||
s[1] = static_cast<utf8_t>(0x80 | (c & 0x3F));
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
s[0] = static_cast<utf8_t>(0xE0 | (c >> 12));
|
||||
s[1] = static_cast<utf8_t>(0x80 | ((c >> 6) & 0x3F));
|
||||
s[2] = static_cast<utf8_t>(0x80 | (c & 0x3F));
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
s[0] = static_cast<utf8_t>(0xF0 | (c >> 18));
|
||||
s[1] = static_cast<utf8_t>(0x80 | ((c >> 12) & 0x3F));
|
||||
s[2] = static_cast<utf8_t>(0x80 | ((c >> 6) & 0x3F));
|
||||
s[3] = static_cast<utf8_t>(0x80 | (c & 0x3F));
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void utf_encodeWchar(utf16_t *s, dchar_t c)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(utf_isValidDchar(c));
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
s[0] = static_cast<utf16_t>(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(sz == 4);
|
||||
memcpy((unsigned char *)s, &c, sz);
|
||||
s[0] = static_cast<utf16_t>((((c - 0x010000) >> 10) & 0x03FF) + 0xD800);
|
||||
s[1] = static_cast<utf16_t>(((c - 0x010000) & 0x03FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
|
||||
void utf_encode(int sz, void *s, dchar_t c)
|
||||
{
|
||||
if (sz == 1)
|
||||
utf_encodeChar((utf8_t *)s, c);
|
||||
else if (sz == 2)
|
||||
utf_encodeWchar((utf16_t *)s, c);
|
||||
else
|
||||
{
|
||||
assert(sz == 4);
|
||||
*((utf32_t *)s) = c;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Decode a UTF-8 sequence as a single UTF-32 code point.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
*/
|
||||
|
||||
const char *utf_decodeChar(utf8_t const *s, size_t len, size_t *pidx, dchar_t *presult)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(pidx != NULL);
|
||||
assert(presult != NULL);
|
||||
size_t i = (*pidx)++;
|
||||
assert(i < len);
|
||||
utf8_t u = s[i];
|
||||
// Pre-stage results for ASCII and error cases
|
||||
*presult = u;
|
||||
|
||||
//printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len);
|
||||
|
||||
// Get expected sequence length
|
||||
unsigned n = UTF8_STRIDE[u];
|
||||
switch (n)
|
||||
{
|
||||
case 1: // ASCII
|
||||
return UTF8_DECODE_OK;
|
||||
case 2: case 3: case 4: // multi-byte UTF-8
|
||||
break;
|
||||
default: // 5- or 6-byte sequence
|
||||
return UTF8_DECODE_OUTSIDE_CODE_SPACE;
|
||||
}
|
||||
if (len < i + n) // source too short
|
||||
return UTF8_DECODE_TRUNCATED_SEQUENCE;
|
||||
|
||||
// Pick off 7 - n low bits from first code unit
|
||||
utf32_t c = u & ((1 << (7 - n)) - 1);
|
||||
/* The following combinations are overlong, and illegal:
|
||||
* 1100000x (10xxxxxx)
|
||||
* 11100000 100xxxxx (10xxxxxx)
|
||||
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
|
||||
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
*/
|
||||
utf8_t u2 = s[++i];
|
||||
if ((u & 0xFE) == 0xC0 || // overlong combination
|
||||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
|
||||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
|
||||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
|
||||
(u == 0xFC && (u2 & 0xFC) == 0x80))
|
||||
return UTF8_DECODE_OVERLONG;
|
||||
// Decode remaining bits
|
||||
for (n += i - 1; i != n; ++i)
|
||||
{
|
||||
u = s[i];
|
||||
if ((u & 0xC0) != 0x80) // trailing bytes are 10xxxxxx
|
||||
return UTF8_DECODE_INVALID_TRAILER;
|
||||
c = (c << 6) | (u & 0x3F);
|
||||
}
|
||||
if (!utf_isValidDchar(c))
|
||||
return UTF8_DECODE_INVALID_CODE_POINT;
|
||||
*pidx = i;
|
||||
*presult = c;
|
||||
return UTF8_DECODE_OK;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Decode a UTF-16 sequence as a single UTF-32 code point.
|
||||
* Returns:
|
||||
* NULL success
|
||||
* !=NULL error message string
|
||||
*/
|
||||
|
||||
const char *utf_decodeWchar(utf16_t const *s, size_t len, size_t *pidx, dchar_t *presult)
|
||||
{
|
||||
assert(s != NULL);
|
||||
assert(pidx != NULL);
|
||||
assert(presult != NULL);
|
||||
size_t i = (*pidx)++;
|
||||
assert(i < len);
|
||||
// Pre-stage results for ASCII and error cases
|
||||
utf32_t u = *presult = s[i];
|
||||
|
||||
if (u < 0x80) // ASCII
|
||||
return UTF16_DECODE_OK;
|
||||
if (0xD800 <= u && u <= 0xDBFF) // Surrogate pair
|
||||
{ if (len <= i + 1)
|
||||
return UTF16_DECODE_TRUNCATED_SEQUENCE;
|
||||
utf16_t u2 = s[i + 1];
|
||||
if (u2 < 0xDC00 || 0xDFFF < u)
|
||||
return UTF16_DECODE_INVALID_SURROGATE;
|
||||
u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
|
||||
++*pidx;
|
||||
}
|
||||
else if (0xDC00 <= u && u <= 0xDFFF)
|
||||
return UTF16_DECODE_UNPAIRED_SURROGATE;
|
||||
if (!utf_isValidDchar(u))
|
||||
return UTF16_DECODE_INVALID_CODE_POINT;
|
||||
*presult = u;
|
||||
return UTF16_DECODE_OK;
|
||||
}
|
||||
|
||||
+99
-10
@@ -11,25 +11,114 @@
|
||||
#ifndef DMD_UTF_H
|
||||
#define DMD_UTF_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef unsigned dchar_t;
|
||||
/// A UTF-8 code unit
|
||||
typedef unsigned char utf8_t;
|
||||
/// A UTF-16 code unit
|
||||
typedef unsigned short utf16_t;
|
||||
/// A UTF-32 code unit
|
||||
typedef unsigned int utf32_t;
|
||||
typedef utf32_t dchar_t;
|
||||
|
||||
int utf_isValidDchar(dchar_t c);
|
||||
namespace Unicode
|
||||
{
|
||||
|
||||
const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult);
|
||||
const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult);
|
||||
static utf16_t const ALPHA_TABLE[][2] =
|
||||
{
|
||||
{ 0x00AA, 0x00AA }, { 0x00B5, 0x00B5 }, { 0x00B7, 0x00B7 }, { 0x00BA, 0x00BA },
|
||||
{ 0x00C0, 0x00D6 }, { 0x00D8, 0x00F6 }, { 0x00F8, 0x01F5 }, { 0x01FA, 0x0217 },
|
||||
{ 0x0250, 0x02A8 }, { 0x02B0, 0x02B8 }, { 0x02BB, 0x02BB }, { 0x02BD, 0x02C1 },
|
||||
{ 0x02D0, 0x02D1 }, { 0x02E0, 0x02E4 }, { 0x037A, 0x037A }, { 0x0386, 0x0386 },
|
||||
{ 0x0388, 0x038A }, { 0x038C, 0x038C }, { 0x038E, 0x03A1 }, { 0x03A3, 0x03CE },
|
||||
{ 0x03D0, 0x03D6 }, { 0x03DA, 0x03DA }, { 0x03DC, 0x03DC }, { 0x03DE, 0x03DE },
|
||||
{ 0x03E0, 0x03E0 }, { 0x03E2, 0x03F3 }, { 0x0401, 0x040C }, { 0x040E, 0x044F },
|
||||
{ 0x0451, 0x045C }, { 0x045E, 0x0481 }, { 0x0490, 0x04C4 }, { 0x04C7, 0x04C8 },
|
||||
{ 0x04CB, 0x04CC }, { 0x04D0, 0x04EB }, { 0x04EE, 0x04F5 }, { 0x04F8, 0x04F9 },
|
||||
{ 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0587 }, { 0x05B0, 0x05B9 },
|
||||
{ 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05D0, 0x05EA },
|
||||
{ 0x05F0, 0x05F2 }, { 0x0621, 0x063A }, { 0x0640, 0x0652 }, { 0x0660, 0x0669 },
|
||||
{ 0x0670, 0x06B7 }, { 0x06BA, 0x06BE }, { 0x06C0, 0x06CE }, { 0x06D0, 0x06DC },
|
||||
{ 0x06E5, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x06F0, 0x06F9 }, { 0x0901, 0x0903 },
|
||||
{ 0x0905, 0x0939 }, { 0x093D, 0x094D }, { 0x0950, 0x0952 }, { 0x0958, 0x0963 },
|
||||
{ 0x0966, 0x096F }, { 0x0981, 0x0983 }, { 0x0985, 0x098C }, { 0x098F, 0x0990 },
|
||||
{ 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 }, { 0x09B2, 0x09B2 }, { 0x09B6, 0x09B9 },
|
||||
{ 0x09BE, 0x09C4 }, { 0x09C7, 0x09C8 }, { 0x09CB, 0x09CD }, { 0x09DC, 0x09DD },
|
||||
{ 0x09DF, 0x09E3 }, { 0x09E6, 0x09F1 }, { 0x0A02, 0x0A02 }, { 0x0A05, 0x0A0A },
|
||||
{ 0x0A0F, 0x0A10 }, { 0x0A13, 0x0A28 }, { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A33 },
|
||||
{ 0x0A35, 0x0A36 }, { 0x0A38, 0x0A39 }, { 0x0A3E, 0x0A42 }, { 0x0A47, 0x0A48 },
|
||||
{ 0x0A4B, 0x0A4D }, { 0x0A59, 0x0A5C }, { 0x0A5E, 0x0A5E }, { 0x0A66, 0x0A6F },
|
||||
{ 0x0A74, 0x0A74 }, { 0x0A81, 0x0A83 }, { 0x0A85, 0x0A8B }, { 0x0A8D, 0x0A8D },
|
||||
{ 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 }, { 0x0AAA, 0x0AB0 }, { 0x0AB2, 0x0AB3 },
|
||||
{ 0x0AB5, 0x0AB9 }, { 0x0ABD, 0x0AC5 }, { 0x0AC7, 0x0AC9 }, { 0x0ACB, 0x0ACD },
|
||||
{ 0x0AD0, 0x0AD0 }, { 0x0AE0, 0x0AE0 }, { 0x0AE6, 0x0AEF }, { 0x0B01, 0x0B03 },
|
||||
{ 0x0B05, 0x0B0C }, { 0x0B0F, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 },
|
||||
{ 0x0B32, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B43 }, { 0x0B47, 0x0B48 },
|
||||
{ 0x0B4B, 0x0B4D }, { 0x0B5C, 0x0B5D }, { 0x0B5F, 0x0B61 }, { 0x0B66, 0x0B6F },
|
||||
{ 0x0B82, 0x0B83 }, { 0x0B85, 0x0B8A }, { 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 },
|
||||
{ 0x0B99, 0x0B9A }, { 0x0B9C, 0x0B9C }, { 0x0B9E, 0x0B9F }, { 0x0BA3, 0x0BA4 },
|
||||
{ 0x0BA8, 0x0BAA }, { 0x0BAE, 0x0BB5 }, { 0x0BB7, 0x0BB9 }, { 0x0BBE, 0x0BC2 },
|
||||
{ 0x0BC6, 0x0BC8 }, { 0x0BCA, 0x0BCD }, { 0x0BE7, 0x0BEF }, { 0x0C01, 0x0C03 },
|
||||
{ 0x0C05, 0x0C0C }, { 0x0C0E, 0x0C10 }, { 0x0C12, 0x0C28 }, { 0x0C2A, 0x0C33 },
|
||||
{ 0x0C35, 0x0C39 }, { 0x0C3E, 0x0C44 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D },
|
||||
{ 0x0C60, 0x0C61 }, { 0x0C66, 0x0C6F }, { 0x0C82, 0x0C83 }, { 0x0C85, 0x0C8C },
|
||||
{ 0x0C8E, 0x0C90 }, { 0x0C92, 0x0CA8 }, { 0x0CAA, 0x0CB3 }, { 0x0CB5, 0x0CB9 },
|
||||
{ 0x0CBE, 0x0CC4 }, { 0x0CC6, 0x0CC8 }, { 0x0CCA, 0x0CCD }, { 0x0CDE, 0x0CDE },
|
||||
{ 0x0CE0, 0x0CE1 }, { 0x0CE6, 0x0CEF }, { 0x0D02, 0x0D03 }, { 0x0D05, 0x0D0C },
|
||||
{ 0x0D0E, 0x0D10 }, { 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 }, { 0x0D3E, 0x0D43 },
|
||||
{ 0x0D46, 0x0D48 }, { 0x0D4A, 0x0D4D }, { 0x0D60, 0x0D61 }, { 0x0D66, 0x0D6F },
|
||||
{ 0x0E01, 0x0E3A }, { 0x0E40, 0x0E5B }, /* { 0x0E50, 0x0E59 }, */ { 0x0E81, 0x0E82 },
|
||||
{ 0x0E84, 0x0E84 }, { 0x0E87, 0x0E88 }, { 0x0E8A, 0x0E8A }, { 0x0E8D, 0x0E8D },
|
||||
{ 0x0E94, 0x0E97 }, { 0x0E99, 0x0E9F }, { 0x0EA1, 0x0EA3 }, { 0x0EA5, 0x0EA5 },
|
||||
{ 0x0EA7, 0x0EA7 }, { 0x0EAA, 0x0EAB }, { 0x0EAD, 0x0EAE }, { 0x0EB0, 0x0EB9 },
|
||||
{ 0x0EBB, 0x0EBD }, { 0x0EC0, 0x0EC4 }, { 0x0EC6, 0x0EC6 }, { 0x0EC8, 0x0ECD },
|
||||
{ 0x0ED0, 0x0ED9 }, { 0x0EDC, 0x0EDD }, { 0x0F00, 0x0F00 }, { 0x0F18, 0x0F19 },
|
||||
{ 0x0F20, 0x0F33 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 },
|
||||
{ 0x0F3E, 0x0F47 }, { 0x0F49, 0x0F69 }, { 0x0F71, 0x0F84 }, { 0x0F86, 0x0F8B },
|
||||
{ 0x0F90, 0x0F95 }, { 0x0F97, 0x0F97 }, { 0x0F99, 0x0FAD }, { 0x0FB1, 0x0FB7 },
|
||||
{ 0x0FB9, 0x0FB9 }, { 0x10A0, 0x10C5 }, { 0x10D0, 0x10F6 }, { 0x1E00, 0x1E9B },
|
||||
{ 0x1EA0, 0x1EF9 }, { 0x1F00, 0x1F15 }, { 0x1F18, 0x1F1D }, { 0x1F20, 0x1F45 },
|
||||
{ 0x1F48, 0x1F4D }, { 0x1F50, 0x1F57 }, { 0x1F59, 0x1F59 }, { 0x1F5B, 0x1F5B },
|
||||
{ 0x1F5D, 0x1F5D }, { 0x1F5F, 0x1F7D }, { 0x1F80, 0x1FB4 }, { 0x1FB6, 0x1FBC },
|
||||
{ 0x1FBE, 0x1FBE }, { 0x1FC2, 0x1FC4 }, { 0x1FC6, 0x1FCC }, { 0x1FD0, 0x1FD3 },
|
||||
{ 0x1FD6, 0x1FDB }, { 0x1FE0, 0x1FEC }, { 0x1FF2, 0x1FF4 }, { 0x1FF6, 0x1FFC },
|
||||
{ 0x203F, 0x2040 }, { 0x207F, 0x207F }, { 0x2102, 0x2102 }, { 0x2107, 0x2107 },
|
||||
{ 0x210A, 0x2113 }, { 0x2115, 0x2115 }, { 0x2118, 0x211D }, { 0x2124, 0x2124 },
|
||||
{ 0x2126, 0x2126 }, { 0x2128, 0x2128 }, { 0x212A, 0x2131 }, { 0x2133, 0x2138 },
|
||||
{ 0x2160, 0x2182 }, { 0x3005, 0x3007 }, { 0x3021, 0x3029 }, { 0x3041, 0x3093 },
|
||||
{ 0x309B, 0x309C }, { 0x30A1, 0x30F6 }, { 0x30FB, 0x30FC }, { 0x3105, 0x312C },
|
||||
{ 0x4E00, 0x9FA5 }, { 0xAC00, 0xD7A3 },
|
||||
};
|
||||
|
||||
const char *utf_validateString(unsigned char *s, size_t len);
|
||||
char const *const UTF8_DECODE_OK = NULL;
|
||||
extern char const UTF8_DECODE_OUTSIDE_CODE_SPACE[];
|
||||
extern char const UTF8_DECODE_TRUNCATED_SEQUENCE[];
|
||||
extern char const UTF8_DECODE_OVERLONG[];
|
||||
extern char const UTF8_DECODE_INVALID_TRAILER[];
|
||||
extern char const UTF8_DECODE_INVALID_CODE_POINT[];
|
||||
|
||||
extern int isUniAlpha(dchar_t);
|
||||
char const *const UTF16_DECODE_OK = NULL;
|
||||
extern char const UTF16_DECODE_TRUNCATED_SEQUENCE[];
|
||||
extern char const UTF16_DECODE_INVALID_SURROGATE[];
|
||||
extern char const UTF16_DECODE_UNPAIRED_SURROGATE[];
|
||||
extern char const UTF16_DECODE_INVALID_CODE_POINT[];
|
||||
|
||||
void utf_encodeChar(unsigned char *s, dchar_t c);
|
||||
void utf_encodeWchar(unsigned short *s, dchar_t c);
|
||||
} // namespace Unicode
|
||||
|
||||
/// \return true if \a c is a valid, non-private UTF-32 code point
|
||||
bool utf_isValidDchar(dchar_t c);
|
||||
|
||||
bool isUniAlpha(dchar_t c);
|
||||
|
||||
int utf_codeLengthChar(dchar_t c);
|
||||
int utf_codeLengthWchar(dchar_t c);
|
||||
|
||||
int utf_codeLength(int sz, dchar_t c);
|
||||
|
||||
void utf_encodeChar(utf8_t *s, dchar_t c);
|
||||
void utf_encodeWchar(utf16_t *s, dchar_t c);
|
||||
void utf_encode(int sz, void *s, dchar_t c);
|
||||
|
||||
#endif
|
||||
const char *utf_decodeChar(utf8_t const *s, size_t len, size_t *pidx, dchar_t *presult);
|
||||
const char *utf_decodeWchar(utf16_t const *s, size_t len, size_t *pidx, dchar_t *presult);
|
||||
|
||||
#endif // DMD_UTF_H
|
||||
|
||||
+6
-4
@@ -23,6 +23,11 @@
|
||||
#include "rmem.h"
|
||||
#include "root.h"
|
||||
|
||||
// stricmp
|
||||
#if __GNUC__ && !_WIN32
|
||||
#include "gnuc.h"
|
||||
#endif
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
#include "mtype.h"
|
||||
@@ -834,10 +839,7 @@ int main(int argc, char** argv)
|
||||
#endif
|
||||
|
||||
if (stricmp(ext, global.mars_ext) == 0 ||
|
||||
stricmp(ext, global.hdr_ext) == 0 ||
|
||||
stricmp(ext, "htm") == 0 ||
|
||||
stricmp(ext, "html") == 0 ||
|
||||
stricmp(ext, "xhtml") == 0)
|
||||
stricmp(ext, global.hdr_ext) == 0)
|
||||
{
|
||||
ext--; // skip onto '.'
|
||||
assert(*ext == '.');
|
||||
|
||||
@@ -384,5 +384,5 @@ if(PHOBOS2_DIR)
|
||||
install(DIRECTORY ${PHOBOS2_DIR}/etc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d")
|
||||
install(FILES ${PHOBOS2_DIR}/crc32.d DESTINATION ${INCLUDE_INSTALL_DIR})
|
||||
endif(PHOBOS2_DIR)
|
||||
install(FILES ${RUNTIME_DIR}/import/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc)
|
||||
install(FILES ${RUNTIME_DIR}/src/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc)
|
||||
install(DIRECTORY ${RUNTIME_DIR}/import/ldc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.di")
|
||||
|
||||
+1
-1
Submodule runtime/druntime updated: 6ac9475aa2...a1cb86b9e1
+1
-1
Submodule runtime/phobos updated: 52b15ed3c0...e05ad809ad
Reference in New Issue
Block a user