Merge branch 'dmd-2.060' into master.

Conflicts:
	dmd2/func.c
	dmd2/mars.c
This commit is contained in:
David Nadlinger
2012-09-07 04:15:44 +02:00
143 changed files with 18692 additions and 18365 deletions
+3
View File
@@ -4,3 +4,6 @@
[submodule "phobos"]
path = runtime/phobos
url = git://github.com/ldc-developers/phobos.git
[submodule "tests/d2/dmd-testsuite"]
path = tests/d2/dmd-testsuite
url = git://github.com/ldc-developers/dmd-testsuite.git
+11 -4
View File
@@ -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
+24
View File
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 2010-2011 by Digital Mars
// Copyright (c) 2010-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -27,6 +27,9 @@
#include "aggregate.h"
#include "hdrgen.h"
#define tfloat2 tfloat64
//#define tfloat2 tcomplex32
/****************************************************
* This breaks a type down into 'simpler' types that can be passed to a function
* in registers, and returned in registers.
@@ -40,6 +43,10 @@ TypeTuple *Type::toArgTypes()
return NULL; // not valid for a parameter
}
TypeTuple *TypeError::toArgTypes()
{
return new TypeTuple(Type::terror);
}
TypeTuple *TypeBasic::toArgTypes()
{ Type *t1 = NULL;
@@ -78,7 +85,7 @@ TypeTuple *TypeBasic::toArgTypes()
case Tcomplex32:
if (global.params.is64bit)
t1 = Type::tfloat64; // weird, eh?
t1 = Type::tfloat2;
else
{
t1 = Type::tfloat64;
@@ -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
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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.
+117 -117
View File
@@ -1,117 +1,117 @@
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The source code and object code supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package.
7. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
8. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The source code and object code supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package.
7. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
8. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
+53 -26
View File
@@ -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
View File
@@ -37,10 +37,10 @@ struct AttribDeclaration : Dsymbol
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void setScopeNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
structalign_t structalign);
void semanticNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
structalign_t structalign);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h> // mem{set|cpy}()
#include "rmem.h"
@@ -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
View File
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // mem{cpy|set}()
#include "root.h"
#include "rmem.h"
@@ -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
View File
@@ -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
View File
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h> // strcmp()
#include "id.h"
#include "init.h"
@@ -266,7 +267,14 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc);
sc->pop();
e = e->optimize(WANTvalue | WANTinterpret);
if (!e->type->checkBoolean())
{
if (e->type->toBasetype() != Type::terror)
exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
inc = 0;
return 0;
}
e = e->ctfeInterpret();
--nest;
if (e->op == TOKerror)
{ exp = e;
+55 -12
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // mem{cpy|set|cmp}()
#include <math.h>
#if __DMC__
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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
View File
@@ -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);
+34
View File
@@ -20,6 +20,10 @@
#include "aggregate.h"
#include "scope.h"
#if IN_LLVM
#include "init.h"
#endif
/********************************************
* Convert from expression to delegate that returns the expression,
* i.e. convert:
@@ -110,6 +114,36 @@ int lambdaCheckForNestedRef(Expression *e, void *param)
*/
switch (e->op)
{
#if IN_LLVM
// We also need to consider the initializers of VarDeclarations in
// DeclarationExps, such as generated for postblit invocation for
// function parameters.
//
// Without this check, e.g. the nested reference to a in the delegate
// create for the lazy argument is not picked up in the following case:
// ---
// struct HasPostblit { this(this) {} }
// struct Foo { HasPostblit _data; }
// void receiver(Foo) {}
// void lazyFunc(E)(lazy E e) { e(); }
// void test() { Foo a; lazyFunc(receiver(a)); }
// ---
case TOKdeclaration:
{ DeclarationExp *de = (DeclarationExp *)e;
if (VarDeclaration *vd = de->declaration->isVarDeclaration())
{
if (vd->init)
{
if (ExpInitializer* ei = vd->init->isExpInitializer())
{
ei->exp->apply(&lambdaCheckForNestedRef, sc);
}
// TODO: Other classes of initializers?
}
}
break;
}
#endif
case TOKsymoff:
{ SymOffExp *se = (SymOffExp *)e;
VarDeclaration *v = se->var->isVarDeclaration();
+87 -25
View File
@@ -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)&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;$(IntDir)\$(InputName).exe&#x0D;&#x0A;"
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo&quot;$(IntDir)\$(InputName).obj&quot; /Fe&quot;$(IntDir)\$(InputName).exe&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;&quot;$(IntDir)\$(InputName).exe&quot;&#x0D;&#x0A;"
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)&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;$(IntDir)\$(InputName).exe&#x0D;&#x0A;"
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo&quot;$(IntDir)\$(InputName).obj&quot; /Fe&quot;$(IntDir)\$(InputName).exe&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;&quot;$(IntDir)\$(InputName).exe&quot;&#x0D;&#x0A;"
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)&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;$(IntDir)\$(InputName).exe&#x0D;&#x0A;"
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo&quot;$(IntDir)\$(InputName).obj&quot; /Fe&quot;$(IntDir)\$(InputName).exe&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;&quot;$(IntDir)\$(InputName).exe&quot;"
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)&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;$(IntDir)\$(InputName).exe&#x0D;&#x0A;"
CommandLine="cl /TP /Itk /Iroot /Ivcbuild /I. /FIwarnings.h /Fo&quot;$(IntDir)\$(InputName).obj&quot; /Fe&quot;$(IntDir)\$(InputName).exe&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;if errorlevel 1 goto VCReportError&#x0D;&#x0A;&quot;$(IntDir)\$(InputName).exe&quot;&#x0D;&#x0A;"
AdditionalDependencies="cc.h;oper.h"
Outputs="optab.c;debtab.c;cdxxx.c;elxxx.c;tytab.c;fltables.c"
/>
+2230 -2229
View File
File diff suppressed because it is too large Load Diff
+1501 -1528
View File
File diff suppressed because it is too large Load Diff
+395 -396
View File
@@ -1,396 +1,395 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-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 DMD_DSYMBOL_H
#define DMD_DSYMBOL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "stringtable.h"
#include "mars.h"
#include "arraytypes.h"
#if IN_LLVM
#if defined(_MSC_VER)
#undef min
#undef max
#endif
#include "../ir/irdsymbol.h"
#endif
struct Identifier;
struct Scope;
struct DsymbolTable;
struct Declaration;
struct ThisDeclaration;
struct TupleDeclaration;
struct TypedefDeclaration;
struct AliasDeclaration;
struct AggregateDeclaration;
struct EnumDeclaration;
struct ClassDeclaration;
struct InterfaceDeclaration;
struct StructDeclaration;
struct UnionDeclaration;
struct FuncDeclaration;
struct FuncAliasDeclaration;
struct FuncLiteralDeclaration;
struct CtorDeclaration;
struct PostBlitDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
struct SharedStaticCtorDeclaration;
struct SharedStaticDtorDeclaration;
struct InvariantDeclaration;
struct UnitTestDeclaration;
struct NewDeclaration;
struct VarDeclaration;
struct AttribDeclaration;
#if IN_DMD
struct Symbol;
#endif
struct Package;
struct Module;
struct Import;
struct Type;
struct TypeTuple;
struct WithStatement;
struct LabelDsymbol;
struct ScopeDsymbol;
struct TemplateDeclaration;
struct TemplateInstance;
struct TemplateMixin;
struct EnumMember;
struct ScopeDsymbol;
struct WithScopeSymbol;
struct ArrayScopeSymbol;
struct StaticStructInitDeclaration;
struct Expression;
struct DeleteDeclaration;
struct HdrGenState;
struct OverloadSet;
struct AA;
#if TARGET_NET
struct PragmaScope;
#endif
#if IN_LLVM
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
#endif
#if IN_GCC
union tree_node;
typedef union tree_node TYPE;
#else
struct TYPE;
#endif
#if IN_LLVM
class Ir;
class IrSymbol;
namespace llvm
{
class Value;
}
#endif
#if IN_DMD
// Back end
struct Classsym;
#endif
enum PROT
{
PROTundefined,
PROTnone, // no access
PROTprivate,
PROTpackage,
PROTprotected,
PROTpublic,
PROTexport,
};
/* State of symbol in winding its way through the passes of the compiler
*/
enum PASS
{
PASSinit, // initial state
PASSsemantic, // semantic() started
PASSsemanticdone, // semantic() done
PASSsemantic2, // semantic2() run
PASSsemantic3, // semantic3() started
PASSsemantic3done, // semantic3() done
PASSobj, // toObjFile() run
};
typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
struct Dsymbol : Object
{
Identifier *ident;
Identifier *c_ident;
Dsymbol *parent;
#if IN_DMD
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
#endif
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
bool errors; // this symbol failed to pass semantic()
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
char *locToChars();
int equals(Object *o);
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();
Dsymbol *pastMixin();
Dsymbol *toParent();
Dsymbol *toParent2();
TemplateInstance *inTemplateInstance();
TemplateInstance *isSpeculative();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
static Dsymbols *arraySyntaxCopy(Dsymbols *a);
virtual const char *toPrettyChars();
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int apply(Dsymbol_apply_ft_t fp, void *param);
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void setScope(Scope *sc);
virtual void importAll(Scope *sc);
virtual void semantic0(Scope *sc);
virtual void semantic(Scope *sc);
virtual void semantic2(Scope *sc);
virtual void semantic3(Scope *sc);
virtual void inlineScan();
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *search_correct(Identifier *id);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
virtual int overloadInsert(Dsymbol *s);
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual void toJsonBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
AggregateDeclaration *isAggregateMember(); // are we a member of an aggregate?
ClassDeclaration *isClassMember(); // are we a member of a class?
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
virtual int isDeprecated(); // is Dsymbol deprecated?
#if DMDV2
virtual int isOverloadable();
virtual int hasOverloads();
#endif
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
virtual char *mangle();
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps, Identifier *ident);
static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL);
virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
virtual int hasPointers();
virtual bool hasStaticCtorOrDtor();
virtual void addLocalClass(ClassDeclarations *) { }
virtual void checkCtorConstInit() { }
virtual void addComment(unsigned char *comment);
virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc);
#if IN_DMD
// Backend
virtual Symbol *toSymbol(); // to backend symbol
virtual void toObjFile(int multiobj); // compile to .obj file
virtual int cvMember(unsigned char *p); // emit cv debug info for member
Symbol *toImport(); // to backend import symbol
static Symbol *toImport(Symbol *s); // to backend import symbol
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
#endif
// Eliminate need for dynamic_cast
virtual Package *isPackage() { return NULL; }
virtual Module *isModule() { return NULL; }
virtual EnumMember *isEnumMember() { return NULL; }
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
virtual TemplateInstance *isTemplateInstance() { return NULL; }
virtual TemplateMixin *isTemplateMixin() { return NULL; }
virtual Declaration *isDeclaration() { return NULL; }
virtual ThisDeclaration *isThisDeclaration() { return NULL; }
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
virtual SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return NULL; }
virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return NULL; }
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
virtual NewDeclaration *isNewDeclaration() { return NULL; }
virtual VarDeclaration *isVarDeclaration() { return NULL; }
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
virtual StructDeclaration *isStructDeclaration() { return NULL; }
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
virtual Import *isImport() { return NULL; }
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
#if TARGET_NET
virtual PragmaScope* isPragmaScope() { return NULL; }
#endif
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);
// llvm stuff
int llvmInternal;
IrDsymbol ir;
IrSymbol* irsym;
#endif
};
// Dsymbol that generates a scope
struct ScopeDsymbol : Dsymbol
{
Dsymbols *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
Dsymbols *imports; // imported Dsymbol's
unsigned char *prots; // array of PROT, one for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void importScope(Dsymbol *s, enum PROT protection);
int isforwardRef();
void defineRef(Dsymbol *s);
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
Dsymbol *nameCollision(Dsymbol *s);
const char *kind();
FuncDeclaration *findGetMembers();
virtual Dsymbol *symtabInsert(Dsymbol *s);
bool hasStaticCtorOrDtor();
void emitMemberComments(Scope *sc);
static size_t dim(Dsymbols *members);
static Dsymbol *getNth(Dsymbols *members, size_t nth, size_t *pn = NULL);
typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
static int foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn=NULL);
ScopeDsymbol *isScopeDsymbol() { return this; }
};
// With statement scope
struct WithScopeSymbol : ScopeDsymbol
{
WithStatement *withstate;
WithScopeSymbol(WithStatement *withstate);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
WithScopeSymbol *isWithScopeSymbol() { return this; }
};
// Array Index/Slice scope
struct ArrayScopeSymbol : ScopeDsymbol
{
Expression *exp; // IndexExp or SliceExp
TypeTuple *type; // for tuple[length]
TupleDeclaration *td; // for tuples of objects
Scope *sc;
ArrayScopeSymbol(Scope *sc, Expression *e);
ArrayScopeSymbol(Scope *sc, TypeTuple *t);
ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
};
// Overload Sets
#if DMDV2
struct OverloadSet : Dsymbol
{
Dsymbols a; // array of Dsymbols
OverloadSet();
void push(Dsymbol *s);
OverloadSet *isOverloadSet() { return this; }
const char *kind();
};
#endif
// Table of Dsymbol's
struct DsymbolTable : Object
{
AA *tab;
DsymbolTable();
~DsymbolTable();
// Look up Identifier. Return Dsymbol if found, NULL if not.
Dsymbol *lookup(Identifier *ident);
// Insert Dsymbol in table. Return NULL if already there.
Dsymbol *insert(Dsymbol *s);
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
Dsymbol *update(Dsymbol *s);
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
};
#endif /* DMD_DSYMBOL_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-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 DMD_DSYMBOL_H
#define DMD_DSYMBOL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "stringtable.h"
#include "mars.h"
#include "arraytypes.h"
#if IN_LLVM
#if defined(_MSC_VER)
#undef min
#undef max
#endif
#include "../ir/irdsymbol.h"
#endif
struct Identifier;
struct Scope;
struct DsymbolTable;
struct Declaration;
struct ThisDeclaration;
struct TupleDeclaration;
struct TypedefDeclaration;
struct AliasDeclaration;
struct AggregateDeclaration;
struct EnumDeclaration;
struct ClassDeclaration;
struct InterfaceDeclaration;
struct StructDeclaration;
struct UnionDeclaration;
struct FuncDeclaration;
struct FuncAliasDeclaration;
struct FuncLiteralDeclaration;
struct CtorDeclaration;
struct PostBlitDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
struct SharedStaticCtorDeclaration;
struct SharedStaticDtorDeclaration;
struct InvariantDeclaration;
struct UnitTestDeclaration;
struct NewDeclaration;
struct VarDeclaration;
struct AttribDeclaration;
#if IN_DMD
struct Symbol;
#endif
struct Package;
struct Module;
struct Import;
struct Type;
struct TypeTuple;
struct WithStatement;
struct LabelDsymbol;
struct ScopeDsymbol;
struct TemplateDeclaration;
struct TemplateInstance;
struct TemplateMixin;
struct EnumMember;
struct ScopeDsymbol;
struct WithScopeSymbol;
struct ArrayScopeSymbol;
struct StaticStructInitDeclaration;
struct Expression;
struct DeleteDeclaration;
struct HdrGenState;
struct OverloadSet;
struct AA;
#if TARGET_NET
struct PragmaScope;
#endif
#if IN_LLVM
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
#endif
#ifdef IN_GCC
union tree_node;
typedef union tree_node TYPE;
#else
struct TYPE;
#endif
#if IN_LLVM
class Ir;
class IrSymbol;
namespace llvm
{
class Value;
}
#endif
#if IN_DMD
// Back end
struct Classsym;
#endif
enum PROT
{
PROTundefined,
PROTnone, // no access
PROTprivate,
PROTpackage,
PROTprotected,
PROTpublic,
PROTexport,
};
/* State of symbol in winding its way through the passes of the compiler
*/
enum PASS
{
PASSinit, // initial state
PASSsemantic, // semantic() started
PASSsemanticdone, // semantic() done
PASSsemantic2, // semantic2() run
PASSsemantic3, // semantic3() started
PASSsemantic3done, // semantic3() done
PASSobj, // toObjFile() run
};
typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
struct Dsymbol : Object
{
Identifier *ident;
Identifier *c_ident;
Dsymbol *parent;
#if IN_DMD
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
#endif
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
bool errors; // this symbol failed to pass semantic()
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
char *locToChars();
int equals(Object *o);
int isAnonymous();
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void error(const char *format, ...) IS_PRINTF(2);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule(); // module where declared
Module *getAccessModule();
Dsymbol *pastMixin();
Dsymbol *toParent();
Dsymbol *toParent2();
TemplateInstance *inTemplateInstance();
TemplateInstance *isSpeculative();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
static Dsymbols *arraySyntaxCopy(Dsymbols *a);
virtual const char *toPrettyChars();
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int apply(Dsymbol_apply_ft_t fp, void *param);
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void setScope(Scope *sc);
virtual void importAll(Scope *sc);
virtual void semantic0(Scope *sc);
virtual void semantic(Scope *sc);
virtual void semantic2(Scope *sc);
virtual void semantic3(Scope *sc);
virtual void inlineScan();
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *search_correct(Identifier *id);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
virtual int overloadInsert(Dsymbol *s);
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual void toJsonBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
AggregateDeclaration *isAggregateMember(); // are we a member of an aggregate?
ClassDeclaration *isClassMember(); // are we a member of a class?
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
virtual int isDeprecated(); // is Dsymbol deprecated?
#if DMDV2
virtual int isOverloadable();
virtual int hasOverloads();
#endif
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
virtual char *mangle();
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps, Identifier *ident);
static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL);
virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
virtual int hasPointers();
virtual bool hasStaticCtorOrDtor();
virtual void addLocalClass(ClassDeclarations *) { }
virtual void checkCtorConstInit() { }
virtual void addComment(unsigned char *comment);
virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc);
#if IN_DMD
// Backend
virtual Symbol *toSymbol(); // to backend symbol
virtual void toObjFile(int multiobj); // compile to .obj file
virtual int cvMember(unsigned char *p); // emit cv debug info for member
Symbol *toImport(); // to backend import symbol
static Symbol *toImport(Symbol *s); // to backend import symbol
Symbol *toSymbolX(const char *prefix, int sclass, TYPE *t, const char *suffix); // helper
#endif
// Eliminate need for dynamic_cast
virtual Package *isPackage() { return NULL; }
virtual Module *isModule() { return NULL; }
virtual EnumMember *isEnumMember() { return NULL; }
virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
virtual TemplateInstance *isTemplateInstance() { return NULL; }
virtual TemplateMixin *isTemplateMixin() { return NULL; }
virtual Declaration *isDeclaration() { return NULL; }
virtual ThisDeclaration *isThisDeclaration() { return NULL; }
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
virtual SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return NULL; }
virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return NULL; }
virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
virtual NewDeclaration *isNewDeclaration() { return NULL; }
virtual VarDeclaration *isVarDeclaration() { return NULL; }
virtual ClassDeclaration *isClassDeclaration() { return NULL; }
virtual StructDeclaration *isStructDeclaration() { return NULL; }
virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
virtual Import *isImport() { return NULL; }
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
#if TARGET_NET
virtual PragmaScope* isPragmaScope() { return NULL; }
#endif
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);
// llvm stuff
int llvmInternal;
IrDsymbol ir;
IrSymbol* irsym;
#endif
};
// Dsymbol that generates a scope
struct ScopeDsymbol : Dsymbol
{
Dsymbols *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
Dsymbols *imports; // imported Dsymbol's
unsigned char *prots; // array of PROT, one for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void importScope(Dsymbol *s, enum PROT protection);
int isforwardRef();
void defineRef(Dsymbol *s);
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
Dsymbol *nameCollision(Dsymbol *s);
const char *kind();
FuncDeclaration *findGetMembers();
virtual Dsymbol *symtabInsert(Dsymbol *s);
bool hasStaticCtorOrDtor();
void emitMemberComments(Scope *sc);
static size_t dim(Dsymbols *members);
static Dsymbol *getNth(Dsymbols *members, size_t nth, size_t *pn = NULL);
typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s);
static int foreach(Scope *sc, Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn=NULL);
ScopeDsymbol *isScopeDsymbol() { return this; }
};
// With statement scope
struct WithScopeSymbol : ScopeDsymbol
{
WithStatement *withstate;
WithScopeSymbol(WithStatement *withstate);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
WithScopeSymbol *isWithScopeSymbol() { return this; }
};
// Array Index/Slice scope
struct ArrayScopeSymbol : ScopeDsymbol
{
Expression *exp; // IndexExp or SliceExp
TypeTuple *type; // for tuple[length]
TupleDeclaration *td; // for tuples of objects
Scope *sc;
ArrayScopeSymbol(Scope *sc, Expression *e);
ArrayScopeSymbol(Scope *sc, TypeTuple *t);
ArrayScopeSymbol(Scope *sc, TupleDeclaration *td);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
};
// Overload Sets
#if DMDV2
struct OverloadSet : Dsymbol
{
Dsymbols a; // array of Dsymbols
OverloadSet();
void push(Dsymbol *s);
OverloadSet *isOverloadSet() { return this; }
const char *kind();
};
#endif
// Table of Dsymbol's
struct DsymbolTable : Object
{
AA *tab;
DsymbolTable();
~DsymbolTable();
// Look up Identifier. Return Dsymbol if found, NULL if not.
Dsymbol *lookup(Identifier *ident);
// Insert Dsymbol in table. Return NULL if already there.
Dsymbol *insert(Dsymbol *s);
// Look for Dsymbol in table. If there, return it. If not, insert s and return that.
Dsymbol *update(Dsymbol *s);
Dsymbol *insert(Identifier *ident, Dsymbol *s); // when ident and s are not the same
};
#endif /* DMD_DSYMBOL_H */
+2 -2
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+15 -5
View File
@@ -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
View File
@@ -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);
#if DMDV2
@@ -1701,17 +1664,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;
@@ -1948,6 +1913,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.
@@ -1992,7 +1999,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).
@@ -2050,7 +2057,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).
@@ -2119,14 +2126,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);
@@ -2488,7 +2509,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();
@@ -2531,7 +2552,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(),
@@ -2617,7 +2638,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);
@@ -2758,14 +2779,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
@@ -3042,6 +3074,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);
}
@@ -3183,12 +3216,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);
@@ -3259,7 +3292,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;
}
@@ -3347,6 +3380,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());
}
@@ -3360,6 +3394,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;
@@ -3674,14 +3709,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)
+248 -248
View File
@@ -1,248 +1,248 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it 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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!
+1 -1
View File
@@ -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);
}
+1
View File
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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 */
+1 -1
View File
@@ -266,7 +266,7 @@ char *TemplateMixin::mangle()
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
buf.printf("%llu%s", (ulonglong)strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
+1640 -1634
View File
File diff suppressed because it is too large Load Diff
+13 -5
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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;
@@ -301,7 +307,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;
@@ -473,7 +481,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();
@@ -493,7 +501,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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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);
-3
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+11 -6
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h> // memset()
#if _MSC_VER
#include <complex>
#else
@@ -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
View File
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -12,6 +12,7 @@
#include <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 ||
+26 -24
View File
@@ -1,24 +1,26 @@
The D Programming Language
Compiler Front End Source
Copyright (c) 1999-2009, by Digital Mars
http://www.digitalmars.com
All Rights Reserved
This is the source code to the front end Digital Mars D compiler.
It covers the lexical analysis, parsing, and semantic analysis
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),
or the Artistic License (attached as artistic.txt).
The optimizer and code generator sources are
covered under a separate license, backendlicense.txt.
It does not apply to anything else distributed by Digital Mars,
including D compiler executables.
-Walter Bright
The D Programming Language
Compiler Front End Source
Copyright (c) 1999-2009, by Digital Mars
http://www.digitalmars.com
All Rights Reserved
This is the source code to the front end Digital Mars D compiler.
It covers the lexical analysis, parsing, and semantic analysis
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 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
covered under a separate license, backendlicense.txt.
It does not apply to anything else distributed by Digital Mars,
including D compiler executables.
-Walter Bright
+9
View File
@@ -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.
*
+8
View File
@@ -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;
-1
View File
@@ -40,7 +40,6 @@
#include "port.h"
#include "root.h"
#include "dchar.h"
#include "rmem.h"
+8
View File
@@ -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>
-482
View File
@@ -1,482 +0,0 @@
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "dchar.h"
#include "rmem.h"
#if M_UNICODE
// Converts a char string to Unicode
dchar *Dchar::dup(char *p)
{
dchar *s;
size_t len;
if (!p)
return NULL;
len = strlen(p);
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
for (unsigned i = 0; i < len; i++)
{
s[i] = (dchar)(p[i] & 0xFF);
}
s[len] = 0;
return s;
}
dchar *Dchar::memchr(dchar *p, int c, int count)
{
int u;
for (u = 0; u < count; u++)
{
if (p[u] == c)
return p + u;
}
return NULL;
}
#if _WIN32 && __DMC__
__declspec(naked)
unsigned Dchar::calcHash(const dchar *str, unsigned len)
{
__asm
{
mov ECX,4[ESP]
mov EDX,8[ESP]
xor EAX,EAX
test EDX,EDX
je L92
LC8: cmp EDX,1
je L98
cmp EDX,2
je LAE
add EAX,[ECX]
// imul EAX,EAX,025h
lea EAX,[EAX][EAX*8]
add ECX,4
sub EDX,2
jmp LC8
L98: mov DX,[ECX]
and EDX,0FFFFh
add EAX,EDX
ret
LAE: add EAX,[ECX]
L92: ret
}
}
#else
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
unsigned hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str;
return hash;
case 2:
hash += *(const uint32_t *)str;
return hash;
default:
hash += *(const uint32_t *)str;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#endif
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash += *(const uint16_t *)str | 0x20;
return hash;
case 2:
hash += *(const uint32_t *)str | 0x200020;
return hash;
default:
hash += *(const uint32_t *)str | 0x200020;
hash *= 37;
str += 2;
len -= 2;
break;
}
}
}
#elif MCBS
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str;
return hash;
case 3:
hash *= 37;
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str;
str += 4;
len -= 4;
break;
}
}
}
#elif UTF8
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
char Dchar::mblen[256] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
};
dchar *Dchar::dec(dchar *pstart, dchar *p)
{
while ((p[-1] & 0xC0) == 0x80)
p--;
return p;
}
int Dchar::get(dchar *p)
{
unsigned c;
unsigned char *q = (unsigned char *)p;
c = q[0];
switch (mblen[c])
{
case 2:
c = ((c - 0xC0) << 6) |
(q[1] - 0x80);
break;
case 3:
c = ((c - 0xE0) << 12) |
((q[1] - 0x80) << 6) |
(q[2] - 0x80);
break;
case 4:
c = ((c - 0xF0) << 18) |
((q[1] - 0x80) << 12) |
((q[2] - 0x80) << 6) |
(q[3] - 0x80);
break;
case 5:
c = ((c - 0xF8) << 24) |
((q[1] - 0x80) << 18) |
((q[2] - 0x80) << 12) |
((q[3] - 0x80) << 6) |
(q[4] - 0x80);
break;
case 6:
c = ((c - 0xFC) << 30) |
((q[1] - 0x80) << 24) |
((q[2] - 0x80) << 18) |
((q[3] - 0x80) << 12) |
((q[4] - 0x80) << 6) |
(q[5] - 0x80);
break;
}
return c;
}
dchar *Dchar::put(dchar *p, unsigned c)
{
if (c <= 0x7F)
{
*p++ = c;
}
else if (c <= 0x7FF)
{
p[0] = 0xC0 + (c >> 6);
p[1] = 0x80 + (c & 0x3F);
p += 2;
}
else if (c <= 0xFFFF)
{
p[0] = 0xE0 + (c >> 12);
p[1] = 0x80 + ((c >> 6) & 0x3F);
p[2] = 0x80 + (c & 0x3F);
p += 3;
}
else if (c <= 0x1FFFFF)
{
p[0] = 0xF0 + (c >> 18);
p[1] = 0x80 + ((c >> 12) & 0x3F);
p[2] = 0x80 + ((c >> 6) & 0x3F);
p[3] = 0x80 + (c & 0x3F);
p += 4;
}
else if (c <= 0x3FFFFFF)
{
p[0] = 0xF8 + (c >> 24);
p[1] = 0x80 + ((c >> 18) & 0x3F);
p[2] = 0x80 + ((c >> 12) & 0x3F);
p[3] = 0x80 + ((c >> 6) & 0x3F);
p[4] = 0x80 + (c & 0x3F);
p += 5;
}
else if (c <= 0x7FFFFFFF)
{
p[0] = 0xFC + (c >> 30);
p[1] = 0x80 + ((c >> 24) & 0x3F);
p[2] = 0x80 + ((c >> 18) & 0x3F);
p[3] = 0x80 + ((c >> 12) & 0x3F);
p[4] = 0x80 + ((c >> 6) & 0x3F);
p[5] = 0x80 + (c & 0x3F);
p += 6;
}
else
assert(0); // not a UCS-4 character
return p;
}
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
#else // ascii
hash_t Dchar::calcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
hash_t Dchar::icalcHash(const dchar *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str | 0x20;
return hash;
case 2:
hash *= 37;
hash += *(const uint16_t *)str | 0x2020;
return hash;
case 3:
hash *= 37;
hash += ((*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]) | 0x202020;
return hash;
default:
hash *= 37;
hash += *(const uint32_t *)str | 0x20202020;
str += 4;
len -= 4;
break;
}
}
}
#endif
#if 0
#include <stdio.h>
void main()
{
// Print out values to hardcode into Dchar::mblen[]
int c;
int s;
for (c = 0; c < 256; c++)
{
s = 1;
if (c >= 0xC0 && c <= 0xDF)
s = 2;
if (c >= 0xE0 && c <= 0xEF)
s = 3;
if (c >= 0xF0 && c <= 0xF7)
s = 4;
if (c >= 0xF8 && c <= 0xFB)
s = 5;
if (c >= 0xFC && c <= 0xFD)
s = 6;
printf("%d", s);
if ((c & 15) == 15)
printf(",\n");
else
printf(",");
}
}
#endif
-194
View File
@@ -1,194 +0,0 @@
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DCHAR_H
#define DCHAR_H
#if __GNUC__ && !_WIN32
#include "gnuc.h"
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#endif
//#include "root.h"
typedef size_t hash_t;
#undef TEXT
// NOTE: All functions accepting pointer arguments must not be NULL
#if M_UNICODE
#include <string.h>
#include <wchar.h>
typedef wchar_t dchar;
#define TEXT(x) L##x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return wcslen(p); }
static dchar get(dchar *p) { return *p; }
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2)
{
#if __DMC__
if (!*s1 && !*s2) // wcscmp is broken
return 0;
#endif
return wcscmp(s1, s2);
#if 0
return (*s1 == *s2)
? wcscmp(s1, s2)
: ((int)*s1 - (int)*s2);
#endif
}
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return iswalpha(c); }
static int isUpper(dchar c) { return iswupper(c); }
static int isLower(dchar c) { return iswlower(c); }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
static dchar *dup(char *p);
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
static dchar *memchr(dchar *p, int c, int count);
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#elif MCBS
#include <limits.h>
#include <mbstring.h>
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax MB_LEN_MAX
#elif UTF8
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 6
struct Dchar
{
static char mblen[256];
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
static dchar *dec(dchar *pstart, dchar *p);
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p);
static int getprev(dchar *pstart, dchar *p)
{ return *dec(pstart, p) & 0xFF; }
static dchar *put(dchar *p, unsigned c);
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
};
#else
#include <string.h>
#ifndef GCC_SAFE_DMD
#include <ctype.h>
#endif
typedef char dchar;
#define TEXT(x) x
#define Dchar_mbmax 1
struct Dchar
{
static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p) { return *p & 0xFF; }
static int getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1] & 0xFF; }
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
#ifndef GCC_SAFE_DMD
static int isAlpha(dchar c) { return isalpha((unsigned char)c); }
static int isUpper(dchar c) { return isupper((unsigned char)c); }
static int isLower(dchar c) { return islower((unsigned char)c); }
static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); }
static int isLocaleLower(dchar c) { return islower((unsigned char)c); }
static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; }
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
#endif
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions
#ifdef __GNUC__
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
#else
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
#endif
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
static hash_t icalcHash(const dchar *str, size_t len);
};
#endif
#endif
+8
View File
@@ -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"
+8
View File
@@ -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
-63
View File
@@ -1,63 +0,0 @@
// lstring.c
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdlib.h>
#include "dchar.h"
#include "rmem.h"
#include "lstring.h"
#ifdef _MSC_VER // prevent compiler internal crash
Lstring Lstring::zero;
#else
Lstring Lstring::zero = LSTRING_EMPTY();
#endif
Lstring *Lstring::ctor(const dchar *p, unsigned length)
{
Lstring *s;
s = alloc(length);
memcpy(s->string, p, length * sizeof(dchar));
return s;
}
Lstring *Lstring::alloc(unsigned length)
{
Lstring *s;
s = (Lstring *)mem.malloc(size(length));
s->length = length;
s->string[length] = 0;
return s;
}
Lstring *Lstring::append(const Lstring *s)
{
Lstring *t;
if (!s->length)
return this;
t = alloc(length + s->length);
memcpy(t->string, string, length * sizeof(dchar));
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
return t;
}
Lstring *Lstring::substring(int start, int end)
{
Lstring *t;
if (start == end)
return &zero;
t = alloc(end - start);
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
return t;
}
-74
View File
@@ -1,74 +0,0 @@
// lstring.h
// length-prefixed strings
// Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef LSTRING_H
#define LSTRING_H 1
#include "dchar.h"
struct Lstring
{
unsigned length;
#ifndef IN_GCC
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
#endif
dchar string[];
static Lstring zero; // 0 length string
// No constructors because we want to be able to statically
// initialize Lstring's, and Lstrings are of variable size.
#if M_UNICODE
#define LSTRING(p,length) { length, L##p }
#else
#define LSTRING(p,length) { length, p }
#endif
#if __GNUC__
#define LSTRING_EMPTY() { 0 }
#else
#define LSTRING_EMPTY() LSTRING("", 0)
#endif
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
static Lstring *ctor(const dchar *p, unsigned length);
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
static Lstring *alloc(unsigned length);
Lstring *clone();
unsigned len() { return length; }
dchar *toDchars() { return string; }
hash_t hash() { return Dchar::calcHash(string, length); }
hash_t ihash() { return Dchar::icalcHash(string, length); }
static int cmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
}
static int icmp(const Lstring *s1, const Lstring *s2)
{
int c = s2->length - s1->length;
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
}
Lstring *append(const Lstring *s);
Lstring *substring(int start, int end);
};
#endif
+18 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -18,6 +18,7 @@
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include <ctype.h>
#if (defined (__SVR4) && defined (__sun))
#include <alloca.h>
@@ -49,7 +50,6 @@
#include "port.h"
#include "root.h"
#include "dchar.h"
#include "rmem.h"
#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);
-10
View File
@@ -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);
+8
View File
@@ -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>
+8
View File
@@ -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
View File
@@ -9,15 +9,70 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h> // uint{8|16|32}_t
#include <string.h> // memcpy()
#include <stdlib.h>
#include "root.h"
#include "rmem.h"
#include "dchar.h"
#include "lstring.h"
#include "rmem.h" // mem
#include "stringtable.h"
hash_t calcHash(const char *str, size_t len)
{
hash_t hash = 0;
while (1)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(const uint8_t *)str;
return hash;
case 2:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint16_t *)str;
#else
hash += str[0] * 256 + str[1];
#endif
return hash;
case 3:
hash *= 37;
#if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2];
#else
hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif
return hash;
default:
hash *= 37;
#if LITTLE_ENDIAN
hash += *(const uint32_t *)str;
#else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif
str += 4;
len -= 4;
break;
}
}
}
void StringValue::ctor(const char *p, unsigned length)
{
this->length = length;
this->lstring[length] = 0;
memcpy(this->lstring, p, length * sizeof(char));
}
void StringTable::init(unsigned size)
{
table = (void **)mem.calloc(size, sizeof(void *));
@@ -46,21 +101,20 @@ struct StringEntry
StringValue value;
static StringEntry *alloc(const dchar *s, unsigned len);
static StringEntry *alloc(const char *s, unsigned len);
};
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
StringEntry *StringEntry::alloc(const char *s, unsigned len)
{
StringEntry *se;
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
se->value.lstring.length = len;
se->hash = Dchar::calcHash(s,len);
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) + len + 1);
se->value.ctor(s, len);
se->hash = calcHash(s,len);
return se;
}
void **StringTable::search(const dchar *s, unsigned len)
void **StringTable::search(const char *s, unsigned len)
{
hash_t hash;
unsigned u;
@@ -68,7 +122,7 @@ void **StringTable::search(const dchar *s, unsigned len)
StringEntry **se;
//printf("StringTable::search(%p,%d)\n",s,len);
hash = Dchar::calcHash(s,len);
hash = calcHash(s,len);
u = hash % tabledim;
se = (StringEntry **)&table[u];
//printf("\thash = %d, u = %d\n",hash,u);
@@ -77,10 +131,10 @@ void **StringTable::search(const dchar *s, unsigned len)
cmp = (*se)->hash - hash;
if (cmp == 0)
{
cmp = (*se)->value.lstring.len() - len;
cmp = (*se)->value.len() - len;
if (cmp == 0)
{
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
cmp = ::memcmp(s,(*se)->value.toDchars(),len);
if (cmp == 0)
break;
}
@@ -94,7 +148,7 @@ void **StringTable::search(const dchar *s, unsigned len)
return (void **)se;
}
StringValue *StringTable::lookup(const dchar *s, unsigned len)
StringValue *StringTable::lookup(const char *s, unsigned len)
{ StringEntry *se;
se = *(StringEntry **)search(s,len);
@@ -104,7 +158,7 @@ StringValue *StringTable::lookup(const dchar *s, unsigned len)
return NULL;
}
StringValue *StringTable::update(const dchar *s, unsigned len)
StringValue *StringTable::update(const char *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
@@ -118,7 +172,7 @@ StringValue *StringTable::update(const dchar *s, unsigned len)
return &se->value;
}
StringValue *StringTable::insert(const dchar *s, unsigned len)
StringValue *StringTable::insert(const char *s, unsigned len)
{ StringEntry **pse;
StringEntry *se;
@@ -133,7 +187,3 @@ StringValue *StringTable::insert(const dchar *s, unsigned len)
}
return &se->value;
}
+32 -9
View File
@@ -1,3 +1,4 @@
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
@@ -15,34 +16,56 @@
#endif
#include "root.h"
#include "dchar.h"
#include "lstring.h"
struct StringEntry;
// StringValue is a variable-length structure as indicated by the last array
// member with unspecified size. It has neither proper c'tors nor a factory
// method because the only thing which should be creating these is StringTable.
struct StringValue
{
union
{ int intvalue;
{
void *ptrvalue;
dchar *string;
char *string;
};
Lstring lstring;
private:
unsigned length;
#ifndef IN_GCC
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
#endif
char lstring[];
public:
unsigned len() const { return length; }
const char *toDchars() const { return lstring; }
private:
friend struct StringEntry;
StringValue(); // not constructible
// This is more like a placement new c'tor
void ctor(const char *p, unsigned length);
};
struct StringTable
{
private:
void **table;
unsigned count;
unsigned tabledim;
public:
void init(unsigned size = 37);
~StringTable();
StringValue *lookup(const dchar *s, unsigned len);
StringValue *insert(const dchar *s, unsigned len);
StringValue *update(const dchar *s, unsigned len);
StringValue *lookup(const char *s, unsigned len);
StringValue *insert(const char *s, unsigned len);
StringValue *update(const char *s, unsigned len);
private:
void **search(const dchar *s, unsigned len);
void **search(const char *s, unsigned len);
};
#endif
+1
View File
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <assert.h>
#include <string.h> // strlen()
#include "root.h"
#include "speller.h"
+2 -2
View File
@@ -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
+180 -70
View File
@@ -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()?
@@ -5353,7 +5443,7 @@ int AsmStatement::comeFrom()
int AsmStatement::blockExit(bool mustNotThrow)
{
if (mustNotThrow)
error("asm statements are assumed to throw", toChars());
error("asm statements are assumed to throw");
// Assume the worst
return BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt;
}
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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);
+6611 -6441
View File
File diff suppressed because it is too large Load Diff
+46 -46
View File
@@ -1,46 +1,46 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_TOTAL_H
#define DMD_TOTAL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <wchar.h>
#include "root.h"
#include "stringtable.h"
#include "arraytypes.h"
#include "mars.h"
#include "lexer.h"
#include "parse.h"
#include "identifier.h"
#include "enum.h"
#include "aggregate.h"
#include "mtype.h"
#include "expression.h"
#include "declaration.h"
#include "statement.h"
#include "scope.h"
#include "import.h"
#include "module.h"
#include "id.h"
#include "cond.h"
#include "version.h"
#include "lib.h"
#endif /* DMD_TOTAL_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_TOTAL_H
#define DMD_TOTAL_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <wchar.h>
#include "root.h"
#include "stringtable.h"
#include "arraytypes.h"
#include "mars.h"
#include "lexer.h"
#include "parse.h"
#include "identifier.h"
#include "enum.h"
#include "aggregate.h"
#include "mtype.h"
#include "expression.h"
#include "declaration.h"
#include "statement.h"
#include "scope.h"
#include "import.h"
#include "module.h"
#include "id.h"
#include "cond.h"
#include "version.h"
#include "lib.h"
#endif /* DMD_TOTAL_H */
+16 -16
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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;
}
+8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -593,7 +593,8 @@ Params parseArgs(int originalArgc, char** originalArgv, ls::Path ldcPath)
goto Lerror;
result.debugLevel = (int)level;
}
result.debugIdentifiers.push_back(p + 7);
else
result.debugIdentifiers.push_back(p + 7);
}
else if (p[6])
goto Lerror;
@@ -616,7 +617,8 @@ Params parseArgs(int originalArgc, char** originalArgv, ls::Path ldcPath)
goto Lerror;
result.versionLevel = (int)level;
}
result.versionIdentifiers.push_back(p + 9);
else
result.versionIdentifiers.push_back(p + 9);
}
else
goto Lerror;
@@ -769,11 +771,11 @@ void buildCommandLine(std::vector<const char*>& r, const Params& p)
if (p.debugFlag) r.push_back("-d-debug");
if (p.debugLevel) r.push_back(concat("-d-debug=", p.debugLevel));
pushSwitches("-d-debug=", p.debugIdentifiers, r);
if (p.debugLevel) r.push_back(concat("-d-version=", p.versionLevel));
if (p.versionLevel) r.push_back(concat("-d-version=", p.versionLevel));
pushSwitches("-d-version=", p.versionIdentifiers, r);
pushSwitches("-L=", p.linkerSwitches, r);
if (p.defaultLibName) r.push_back(concat("-defaultlib=", p.defaultLibName));
if (p.debugLibName) r.push_back(concat("-deps=", p.moduleDepsFile));
if (p.debugLibName) r.push_back(concat("-debuglib=", p.debugLibName));
if (p.hiddenDebugB) r.push_back("-hidden-debug-b");
if (p.hiddenDebugC) r.push_back("-hidden-debug-c");
if (p.hiddenDebugF) r.push_back("-hidden-debug-f");
+7 -168
View File
@@ -58,167 +58,6 @@ void linkModules(llvm::Module* dst, const Module_vector& MV)
static llvm::sys::Path gExePath;
int linkExecutable(const char* argv0)
{
Logger::println("*** Linking executable ***");
// error string
std::string errstr;
// find the llvm-ld program
llvm::sys::Path ldpath = llvm::sys::Program::FindProgramByName("llvm-ld");
if (ldpath.isEmpty())
{
ldpath.set("llvm-ld");
}
// build arguments
std::vector<const char*> args;
// first the program name ??
args.push_back("llvm-ld");
// output filename
std::string exestr;
if (global.params.exefile)
{ // explicit
exestr = global.params.exefile;
}
else
{ // inferred
// try root module name
if (Module::rootModule)
exestr = Module::rootModule->toChars();
else
exestr = "a.out";
}
if (global.params.os == OSWindows && !(exestr.substr(exestr.length()-4) == ".exe"))
exestr.append(".exe");
std::string outopt = "-o=" + exestr;
args.push_back(outopt.c_str());
// set the global gExePath
gExePath.set(exestr);
assert(gExePath.isValid());
// create path to exe
llvm::sys::Path exedir(llvm::sys::path::parent_path(gExePath.str()));
if (!llvm::sys::fs::exists(exedir.str()))
{
exedir.createDirectoryOnDisk(true, &errstr);
if (!errstr.empty())
{
error("failed to create path to linking output: %s\n%s", exedir.c_str(), errstr.c_str());
fatal();
}
}
// strip debug info
if (!global.params.symdebug)
args.push_back("-strip-debug");
// optimization level
if (!optimize())
args.push_back("-disable-opt");
else
{
switch(optLevel())
{
case 0:
args.push_back("-disable-opt");
break;
case 1:
args.push_back("-globaldce");
args.push_back("-disable-opt");
args.push_back("-globaldce");
args.push_back("-mem2reg");
case 2:
case 3:
case 4:
case 5:
// use default optimization
break;
default:
assert(0);
}
}
// inlining
if (!(global.params.useInline || doInline()))
{
args.push_back("-disable-inlining");
}
// additional linker switches
for (unsigned i = 0; i < global.params.linkswitches->dim; i++)
{
char *p = static_cast<char *>(global.params.linkswitches->data[i]);
args.push_back(p);
}
// native please
args.push_back("-native");
// user libs
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
{
char *p = static_cast<char *>(global.params.libfiles->data[i]);
args.push_back(p);
}
// default libs
switch(global.params.os) {
case OSLinux:
case OSMacOSX:
args.push_back("-ldl");
case OSFreeBSD:
args.push_back("-lpthread");
args.push_back("-lm");
break;
case OSHaiku:
args.push_back("-lroot");
break;
case OSWindows:
// FIXME: I'd assume kernel32 etc
break;
}
// object files
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
{
char *p = static_cast<char *>(global.params.objfiles->data[i]);
args.push_back(p);
}
// print link command?
if (!quiet || global.params.verbose)
{
// Print it
for (int i = 0; i < args.size(); i++)
printf("%s ", args[i]);
printf("\n");
fflush(stdout);
}
// terminate args list
args.push_back(NULL);
// try to call linker!!!
if (int status = llvm::sys::Program::ExecuteAndWait(ldpath, &args[0], NULL, NULL, 0,0, &errstr))
{
error("linking failed:\nstatus: %d", status);
if (!errstr.empty())
error("message: %s", errstr.c_str());
return status;
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
int linkObjToBinary(bool sharedLib)
{
Logger::println("*** Linking executable ***");
@@ -244,6 +83,13 @@ int linkObjToBinary(bool sharedLib)
args.push_back(p);
}
// user libs
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
{
char *p = static_cast<char *>(global.params.libfiles->data[i]);
args.push_back(p);
}
// output filename
std::string output;
if (!sharedLib && global.params.exefile)
@@ -308,13 +154,6 @@ int linkObjToBinary(bool sharedLib)
args.push_back(p);
}
// user libs
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
{
char *p = static_cast<char *>(global.params.libfiles->data[i]);
args.push_back(p);
}
// default libs
bool addSoname = false;
switch(global.params.os) {
+2 -9
View File
@@ -18,13 +18,6 @@ namespace llvm
*/
void linkModules(llvm::Module* dst, const std::vector<llvm::Module*>& MV);
/**
* Link an executable.
* @param argv0 the argv[0] value as passed to main
* @return 0 on success.
*/
int linkExecutable(const char* argv0);
/**
* Link an executable only from object files.
* @param argv0 the argv[0] value as passed to main
@@ -38,12 +31,12 @@ int linkObjToBinary(bool sharedLib);
void createStaticLibrary();
/**
* Delete the executable that was previously linked with linkExecutable.
* Delete the executable that was previously linked with linkObjToBinary.
*/
void deleteExecutable();
/**
* Runs the executable that was previously linked with linkExecutable.
* Runs the executable that was previously linked with linkObjToBinary.
* @return the return status of the executable.
*/
int runExecutable();
+6 -4
View File
@@ -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"
@@ -835,10 +840,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 == '.');
+4 -1
View File
@@ -208,7 +208,10 @@ void DtoArrayAssign(DValue *array, DValue *value, int op)
assert(value && array);
assert(op != TOKblit);
Type *t = value->type->toBasetype();
// Use array->type instead of value->type so as to not accidentally pick
// up a superfluous const layer (TypeInfo_Const doesn't pass on postblit()).
Type *t = array->type->toBasetype();
assert(t->nextOf());
Type *elemType = t->nextOf()->toBasetype();
+1 -1
View File
@@ -2189,7 +2189,7 @@ namespace AsmParserx8632
*/
if ( isDollar ( e ) )
{
error ( "dollar labels are not supported", stmt->loc.toChars() );
stmt->error("dollar labels are not supported");
asmcode->dollarLabel = 1;
}
else if ( e->op == TOKdsymbol )
+1 -1
View File
@@ -2325,7 +2325,7 @@ namespace AsmParserx8664
*/
if ( isDollar ( e ) )
{
error ( "dollar labels are not supported", stmt->loc.toChars() );
stmt->error("dollar labels are not supported");
asmcode->dollarLabel = 1;
}
else if ( e->op == TOKdsymbol )
+1 -1
View File
@@ -187,7 +187,7 @@ int AsmStatement::blockExit(bool mustNotThrow)
//printf("AsmStatement::blockExit(%p)\n", this);
#if DMDV2
if (mustNotThrow)
error("asm statements are assumed to throw", toChars());
error("asm statements are assumed to throw");
#endif
// Assume the worst
return BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt;
+14 -10
View File
@@ -676,7 +676,7 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
// OffsetTypeInfo[] offTi;
// void *defaultConstructor;
// version(D_Version2)
// const(MemberInfo[]) function(string) xgetMembers;
// immutable(void)* m_RTInfo;
// else
// TypeInfo typeinfo; // since dmd 1.045
// }
@@ -761,10 +761,12 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
b.push_funcptr(cd->inv, invVar->type);
// uint flags
unsigned flags;
if (cd->isInterfaceDeclaration())
b.push_uint(4 | cd->isCOMinterface() | 32);
flags = 4 | cd->isCOMinterface() | 32;
else
b.push_uint(build_classinfo_flags(cd));
flags = build_classinfo_flags(cd);
b.push_uint(flags);
// deallocator
b.push_funcptr(cd->aggDelete, Type::tvoid->pointerTo());
@@ -790,16 +792,18 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
b.push_funcptr(cd->defaultCtor, defConstructorVar->type);
#if DMDV2
// xgetMembers
VarDeclaration* xgetVar = static_cast<VarDeclaration*>(cinfo->fields.data[11]);
b.push_funcptr(cd->findGetMembers(), xgetVar->type);
// immutable(void)* m_RTInfo;
// The cases where getRTInfo is null are not quite here, but the code is
// modelled after what DMD does.
if (cd->getRTInfo)
b.push(cd->getRTInfo->toConstElem(gIR));
else if (flags & 2)
b.push_size_as_vp(0); // no pointers
else
b.push_size_as_vp(1); // has pointers
#else
// typeinfo - since 1.045
b.push_typeinfo(cd->type);
#endif
/*size_t n = inits.size();
+11 -2
View File
@@ -16,6 +16,8 @@ DVarValue::DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue)
: DValue(t), var(vd), val(llvmValue)
{
assert(isaPointer(llvmValue));
assert(!isSpecialRefVar(vd) ||
isaPointer(isaPointer(llvmValue)->getElementType()));
}
DVarValue::DVarValue(Type* t, LLValue* llvmValue)
@@ -27,6 +29,8 @@ DVarValue::DVarValue(Type* t, LLValue* llvmValue)
LLValue* DVarValue::getLVal()
{
assert(val);
if (var && isSpecialRefVar(var))
return DtoLoad(val);
return val;
}
@@ -34,9 +38,14 @@ LLValue* DVarValue::getRVal()
{
assert(val);
Type* bt = type->toBasetype();
LLValue* tmp = val;
if (var && isSpecialRefVar(var))
tmp = DtoLoad(tmp);
if (DtoIsPassedByRef(bt))
return val;
return DtoLoad(val);
return tmp;
return DtoLoad(tmp);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
+5 -6
View File
@@ -807,16 +807,15 @@ void DtoDefineFunction(FuncDeclaration* fd)
DtoCreateNestedContext(fd);
if (fd->vresult && !
#if DMDV2
if (fd->vresult && fd->vresult->nestedrefs.dim) // FIXME: not sure here :/
fd->vresult->nestedrefs.dim // FIXME: not sure here :/
#else
if (fd->vresult && fd->vresult->nestedref)
fd->vresult->nestedref
#endif
)
{
DtoNestedInit(fd->vresult);
} else if (fd->vresult) {
fd->vresult->ir.irLocal = new IrLocal(fd->vresult);
fd->vresult->ir.irLocal->value = DtoAlloca(fd->vresult->type, fd->vresult->toChars());
DtoVarDeclaration(fd->vresult);
}
// copy _argptr and _arguments to a memory location
+175 -175
View File
@@ -1,175 +1,175 @@
/* DMDFE backend stubs
* This file contains the implementations of the backend routines.
* For dmdfe these do nothing but print a message saying the module
* has been parsed. Substitute your own behaviors for these routimes.
*/
#include <cstdarg>
#include "gen/llvm.h"
#include "mtype.h"
#include "declaration.h"
#include "statement.h"
#include "gen/irstate.h"
#include "tollvm.h"
IRState* gIR = 0;
llvm::TargetMachine* gTargetMachine = 0;
const llvm::TargetData* gTargetData = 0;
TargetABI* gABI = 0;
//////////////////////////////////////////////////////////////////////////////////////////
IRScope::IRScope()
: builder(gIR->context())
{
begin = end = NULL;
}
IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
: builder(b)
{
begin = b;
end = e;
}
const IRScope& IRScope::operator=(const IRScope& rhs)
{
begin = rhs.begin;
end = rhs.end;
builder.SetInsertPoint(begin);
return *this;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRTargetScope::IRTargetScope()
{
}
IRTargetScope::IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget)
{
this->s = s;
this->enclosinghandler = enclosinghandler;
this->breakTarget = breakTarget;
this->continueTarget = continueTarget;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRState::IRState(llvm::Module* m)
: module(m), dibuilder(*m)
{
interfaceInfoType = NULL;
mutexType = NULL;
moduleRefType = NULL;
dmodule = 0;
emitMain = false;
mainFunc = 0;
ir.state = this;
asmBlock = NULL;
}
IrFunction* IRState::func()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back();
}
llvm::Function* IRState::topfunc()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back()->func;
}
TypeFunction* IRState::topfunctype()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back()->type;
}
llvm::Instruction* IRState::topallocapoint()
{
assert(!functions.empty() && "AllocaPoint stack is empty!");
return functions.back()->allocapoint;
}
IrStruct* IRState::topstruct()
{
assert(!structs.empty() && "Struct vector is empty!");
return structs.back();
}
IRScope& IRState::scope()
{
assert(!scopes.empty());
return scopes.back();
}
llvm::BasicBlock* IRState::scopebb()
{
IRScope& s = scope();
assert(s.begin);
return s.begin;
}
llvm::BasicBlock* IRState::scopeend()
{
IRScope& s = scope();
assert(s.end);
return s.end;
}
bool IRState::scopereturned()
{
//return scope().returned;
return !scopebb()->empty() && scopebb()->back().isTerminator();
}
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, const char* Name)
{
LLSmallVector<LLValue*, 1> args;
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name)
{
LLSmallVector<LLValue*, 1> args;
args.push_back(Arg1);
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name)
{
LLSmallVector<LLValue*, 2> args;
args.push_back(Arg1);
args.push_back(Arg2);
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name)
{
LLSmallVector<LLValue*, 3> args;
args.push_back(Arg1);
args.push_back(Arg2);
args.push_back(Arg3);
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name)
{
LLSmallVector<LLValue*, 4> args;
args.push_back(Arg1);
args.push_back(Arg2);
args.push_back(Arg3);
args.push_back(Arg4);
return CreateCallOrInvoke(Callee, args, Name);
}
//////////////////////////////////////////////////////////////////////////////////////////
IRBuilder<>* IRBuilderHelper::operator->()
{
IRBuilder<>& b = state->scope().builder;
assert(b.GetInsertBlock() != NULL);
return &b;
}
/* DMDFE backend stubs
* This file contains the implementations of the backend routines.
* For dmdfe these do nothing but print a message saying the module
* has been parsed. Substitute your own behaviors for these routimes.
*/
#include <cstdarg>
#include "gen/llvm.h"
#include "mtype.h"
#include "declaration.h"
#include "statement.h"
#include "gen/irstate.h"
#include "tollvm.h"
IRState* gIR = 0;
llvm::TargetMachine* gTargetMachine = 0;
const llvm::TargetData* gTargetData = 0;
TargetABI* gABI = 0;
//////////////////////////////////////////////////////////////////////////////////////////
IRScope::IRScope()
: builder(gIR->context())
{
begin = end = NULL;
}
IRScope::IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e)
: builder(b)
{
begin = b;
end = e;
}
const IRScope& IRScope::operator=(const IRScope& rhs)
{
begin = rhs.begin;
end = rhs.end;
builder.SetInsertPoint(begin);
return *this;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRTargetScope::IRTargetScope()
{
}
IRTargetScope::IRTargetScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* continueTarget, llvm::BasicBlock* breakTarget)
{
this->s = s;
this->enclosinghandler = enclosinghandler;
this->breakTarget = breakTarget;
this->continueTarget = continueTarget;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRState::IRState(llvm::Module* m)
: module(m), dibuilder(*m)
{
interfaceInfoType = NULL;
mutexType = NULL;
moduleRefType = NULL;
dmodule = 0;
emitMain = false;
mainFunc = 0;
ir.state = this;
asmBlock = NULL;
}
IrFunction* IRState::func()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back();
}
llvm::Function* IRState::topfunc()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back()->func;
}
TypeFunction* IRState::topfunctype()
{
assert(!functions.empty() && "Function stack is empty!");
return functions.back()->type;
}
llvm::Instruction* IRState::topallocapoint()
{
assert(!functions.empty() && "AllocaPoint stack is empty!");
return functions.back()->allocapoint;
}
IrStruct* IRState::topstruct()
{
assert(!structs.empty() && "Struct vector is empty!");
return structs.back();
}
IRScope& IRState::scope()
{
assert(!scopes.empty());
return scopes.back();
}
llvm::BasicBlock* IRState::scopebb()
{
IRScope& s = scope();
assert(s.begin);
return s.begin;
}
llvm::BasicBlock* IRState::scopeend()
{
IRScope& s = scope();
assert(s.end);
return s.end;
}
bool IRState::scopereturned()
{
//return scope().returned;
return !scopebb()->empty() && scopebb()->back().isTerminator();
}
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, const char* Name)
{
LLSmallVector<LLValue*, 1> args;
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name)
{
LLSmallVector<LLValue*, 1> args;
args.push_back(Arg1);
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name)
{
LLSmallVector<LLValue*, 2> args;
args.push_back(Arg1);
args.push_back(Arg2);
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name)
{
LLSmallVector<LLValue*, 3> args;
args.push_back(Arg1);
args.push_back(Arg2);
args.push_back(Arg3);
return CreateCallOrInvoke(Callee, args, Name);
}
LLCallSite IRState::CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name)
{
LLSmallVector<LLValue*, 4> args;
args.push_back(Arg1);
args.push_back(Arg2);
args.push_back(Arg3);
args.push_back(Arg4);
return CreateCallOrInvoke(Callee, args, Name);
}
//////////////////////////////////////////////////////////////////////////////////////////
IRBuilder<>* IRBuilderHelper::operator->()
{
IRBuilder<>& b = state->scope().builder;
assert(b.GetInsertBlock() != NULL);
return &b;
}
+234 -234
View File
@@ -1,234 +1,234 @@
#ifndef LDC_GEN_IRSTATE_H
#define LDC_GEN_IRSTATE_H
#include <vector>
#include <deque>
#include <list>
#include <sstream>
#include "root.h"
#include "aggregate.h"
#include "ir/irfunction.h"
#include "ir/irstruct.h"
#include "ir/irvar.h"
#if LDC_LLVM_VER >= 302
#include "llvm/DIBuilder.h"
#else
#include "llvm/Analysis/DIBuilder.h"
#endif
#include "llvm/Support/CallSite.h"
namespace llvm {
class LLVMContext;
class TargetMachine;
}
// global ir state for current module
struct IRState;
struct TargetABI;
extern IRState* gIR;
extern llvm::TargetMachine* gTargetMachine;
extern const llvm::TargetData* gTargetData;
extern TargetABI* gABI;
struct TypeFunction;
struct TypeStruct;
struct ClassDeclaration;
struct FuncDeclaration;
struct Module;
struct TypeStruct;
struct BaseClass;
struct AnonDeclaration;
struct IrModule;
// represents a scope
struct IRScope
{
llvm::BasicBlock* begin;
llvm::BasicBlock* end;
IRBuilder<> builder;
IRScope();
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
const IRScope& operator=(const IRScope& rhs);
#if DMDV2
// list of variables needing destruction
std::vector<VarDeclaration*> varsInScope;
#endif
};
struct IRBuilderHelper
{
IRState* state;
IRBuilder<>* operator->();
};
struct IRAsmStmt
{
IRAsmStmt()
: isBranchToLabel(NULL) {}
std::string code;
std::string out_c;
std::string in_c;
std::vector<LLValue*> out;
std::vector<LLValue*> in;
// if this is nonzero, it contains the target label
Identifier* isBranchToLabel;
};
struct IRAsmBlock
{
std::deque<IRAsmStmt*> s;
std::set<std::string> clobs;
size_t outputcount;
// stores the labels within the asm block
std::vector<Identifier*> internalLabels;
AsmBlockStatement* asmBlock;
LLType* retty;
unsigned retn;
bool retemu; // emulate abi ret with a temporary
LLValue* (*retfixup)(IRBuilderHelper b, LLValue* orig); // Modifies retval
IRAsmBlock(AsmBlockStatement* b)
: outputcount(0), asmBlock(b), retty(NULL), retn(0), retemu(false),
retfixup(NULL)
{}
};
// represents the module
struct IRState
{
IRState(llvm::Module* m);
// module
Module* dmodule;
llvm::Module* module;
// interface info type, used in DtoInterfaceInfoType
LLStructType* interfaceInfoType;
LLStructType* mutexType;
LLStructType* moduleRefType;
// helper to get the LLVMContext of the module
llvm::LLVMContext& context() const { return module->getContext(); }
// functions
typedef std::vector<IrFunction*> FunctionVector;
FunctionVector functions;
IrFunction* func();
llvm::Function* topfunc();
TypeFunction* topfunctype();
llvm::Instruction* topallocapoint();
// structs
typedef std::vector<IrStruct*> StructVector;
StructVector structs;
IrStruct* topstruct();
// D main function
bool emitMain;
llvm::Function* mainFunc;
// basic block scopes
std::vector<IRScope> scopes;
IRScope& scope();
#if DMDV2
std::vector<VarDeclaration*> &varsInScope() { return scope().varsInScope; }
#endif
llvm::BasicBlock* scopebb();
llvm::BasicBlock* scopeend();
bool scopereturned();
// create a call or invoke, depending on the landing pad info
// the template function is defined further down in this file
template <typename T>
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const T& args, const char* Name="");
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const char* Name="");
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name="");
llvm::CallSite CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name="");
llvm::CallSite CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name="");
llvm::CallSite CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name="");
// this holds the array being indexed or sliced so $ will work
// might be a better way but it works. problem is I only get a
// VarDeclaration for __dollar, but I can't see how to get the
// array pointer from this :(
std::vector<DValue*> arrays;
// builder helper
IRBuilderHelper ir;
// debug info helper
llvm::DIBuilder dibuilder;
// static ctors/dtors/unittests
typedef std::list<FuncDeclaration*> FuncDeclList;
typedef std::list<VarDeclaration*> GatesList;
FuncDeclList ctors;
FuncDeclList dtors;
#if DMDV2
FuncDeclList sharedCtors;
FuncDeclList sharedDtors;
GatesList gates;
GatesList sharedGates;
#endif
FuncDeclList unitTests;
// all template instances that had members emitted
// currently only filled for singleobj
// used to make sure the complete template instance gets emitted in the
// first file that touches a member, see #318
typedef std::set<TemplateInstance*> TemplateInstanceSet;
TemplateInstanceSet seenTemplateInstances;
// for inline asm
IRAsmBlock* asmBlock;
std::ostringstream nakedAsm;
// 'used' array solely for keeping a reference to globals
std::vector<LLConstant*> usedArray;
};
template <typename T>
llvm::CallSite IRState::CreateCallOrInvoke(LLValue* Callee, const T &args, const char* Name)
{
llvm::BasicBlock* pad = func()->gen->landingPad;
if(pad)
{
// intrinsics don't support invoking and 'nounwind' functions don't need it.
LLFunction* funcval = llvm::dyn_cast<LLFunction>(Callee);
if (funcval && (funcval->isIntrinsic() || funcval->doesNotThrow()))
{
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
call->setAttributes(funcval->getAttributes());
return call;
}
llvm::BasicBlock* postinvoke = llvm::BasicBlock::Create(gIR->context(), "postinvoke", topfunc(), scopeend());
llvm::InvokeInst* invoke = ir->CreateInvoke(Callee, postinvoke, pad, args, Name);
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
invoke->setAttributes(fn->getAttributes());
scope() = IRScope(postinvoke, scopeend());
return invoke;
}
else
{
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
call->setAttributes(fn->getAttributes());
return call;
}
}
#endif // LDC_GEN_IRSTATE_H
#ifndef LDC_GEN_IRSTATE_H
#define LDC_GEN_IRSTATE_H
#include <vector>
#include <deque>
#include <list>
#include <sstream>
#include "root.h"
#include "aggregate.h"
#include "ir/irfunction.h"
#include "ir/irstruct.h"
#include "ir/irvar.h"
#if LDC_LLVM_VER >= 302
#include "llvm/DIBuilder.h"
#else
#include "llvm/Analysis/DIBuilder.h"
#endif
#include "llvm/Support/CallSite.h"
namespace llvm {
class LLVMContext;
class TargetMachine;
}
// global ir state for current module
struct IRState;
struct TargetABI;
extern IRState* gIR;
extern llvm::TargetMachine* gTargetMachine;
extern const llvm::TargetData* gTargetData;
extern TargetABI* gABI;
struct TypeFunction;
struct TypeStruct;
struct ClassDeclaration;
struct FuncDeclaration;
struct Module;
struct TypeStruct;
struct BaseClass;
struct AnonDeclaration;
struct IrModule;
// represents a scope
struct IRScope
{
llvm::BasicBlock* begin;
llvm::BasicBlock* end;
IRBuilder<> builder;
IRScope();
IRScope(llvm::BasicBlock* b, llvm::BasicBlock* e);
const IRScope& operator=(const IRScope& rhs);
#if DMDV2
// list of variables needing destruction
std::vector<VarDeclaration*> varsInScope;
#endif
};
struct IRBuilderHelper
{
IRState* state;
IRBuilder<>* operator->();
};
struct IRAsmStmt
{
IRAsmStmt()
: isBranchToLabel(NULL) {}
std::string code;
std::string out_c;
std::string in_c;
std::vector<LLValue*> out;
std::vector<LLValue*> in;
// if this is nonzero, it contains the target label
Identifier* isBranchToLabel;
};
struct IRAsmBlock
{
std::deque<IRAsmStmt*> s;
std::set<std::string> clobs;
size_t outputcount;
// stores the labels within the asm block
std::vector<Identifier*> internalLabels;
AsmBlockStatement* asmBlock;
LLType* retty;
unsigned retn;
bool retemu; // emulate abi ret with a temporary
LLValue* (*retfixup)(IRBuilderHelper b, LLValue* orig); // Modifies retval
IRAsmBlock(AsmBlockStatement* b)
: outputcount(0), asmBlock(b), retty(NULL), retn(0), retemu(false),
retfixup(NULL)
{}
};
// represents the module
struct IRState
{
IRState(llvm::Module* m);
// module
Module* dmodule;
llvm::Module* module;
// interface info type, used in DtoInterfaceInfoType
LLStructType* interfaceInfoType;
LLStructType* mutexType;
LLStructType* moduleRefType;
// helper to get the LLVMContext of the module
llvm::LLVMContext& context() const { return module->getContext(); }
// functions
typedef std::vector<IrFunction*> FunctionVector;
FunctionVector functions;
IrFunction* func();
llvm::Function* topfunc();
TypeFunction* topfunctype();
llvm::Instruction* topallocapoint();
// structs
typedef std::vector<IrStruct*> StructVector;
StructVector structs;
IrStruct* topstruct();
// D main function
bool emitMain;
llvm::Function* mainFunc;
// basic block scopes
std::vector<IRScope> scopes;
IRScope& scope();
#if DMDV2
std::vector<VarDeclaration*> &varsInScope() { return scope().varsInScope; }
#endif
llvm::BasicBlock* scopebb();
llvm::BasicBlock* scopeend();
bool scopereturned();
// create a call or invoke, depending on the landing pad info
// the template function is defined further down in this file
template <typename T>
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const T& args, const char* Name="");
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, const char* Name="");
llvm::CallSite CreateCallOrInvoke(LLValue* Callee, LLValue* Arg1, const char* Name="");
llvm::CallSite CreateCallOrInvoke2(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, const char* Name="");
llvm::CallSite CreateCallOrInvoke3(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, const char* Name="");
llvm::CallSite CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* Arg2, LLValue* Arg3, LLValue* Arg4, const char* Name="");
// this holds the array being indexed or sliced so $ will work
// might be a better way but it works. problem is I only get a
// VarDeclaration for __dollar, but I can't see how to get the
// array pointer from this :(
std::vector<DValue*> arrays;
// builder helper
IRBuilderHelper ir;
// debug info helper
llvm::DIBuilder dibuilder;
// static ctors/dtors/unittests
typedef std::list<FuncDeclaration*> FuncDeclList;
typedef std::list<VarDeclaration*> GatesList;
FuncDeclList ctors;
FuncDeclList dtors;
#if DMDV2
FuncDeclList sharedCtors;
FuncDeclList sharedDtors;
GatesList gates;
GatesList sharedGates;
#endif
FuncDeclList unitTests;
// all template instances that had members emitted
// currently only filled for singleobj
// used to make sure the complete template instance gets emitted in the
// first file that touches a member, see #318
typedef std::set<TemplateInstance*> TemplateInstanceSet;
TemplateInstanceSet seenTemplateInstances;
// for inline asm
IRAsmBlock* asmBlock;
std::ostringstream nakedAsm;
// 'used' array solely for keeping a reference to globals
std::vector<LLConstant*> usedArray;
};
template <typename T>
llvm::CallSite IRState::CreateCallOrInvoke(LLValue* Callee, const T &args, const char* Name)
{
llvm::BasicBlock* pad = func()->gen->landingPad;
if(pad)
{
// intrinsics don't support invoking and 'nounwind' functions don't need it.
LLFunction* funcval = llvm::dyn_cast<LLFunction>(Callee);
if (funcval && (funcval->isIntrinsic() || funcval->doesNotThrow()))
{
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
call->setAttributes(funcval->getAttributes());
return call;
}
llvm::BasicBlock* postinvoke = llvm::BasicBlock::Create(gIR->context(), "postinvoke", topfunc(), scopeend());
llvm::InvokeInst* invoke = ir->CreateInvoke(Callee, postinvoke, pad, args, Name);
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
invoke->setAttributes(fn->getAttributes());
scope() = IRScope(postinvoke, scopeend());
return invoke;
}
else
{
llvm::CallInst* call = ir->CreateCall(Callee, args, Name);
if (LLFunction* fn = llvm::dyn_cast<LLFunction>(Callee))
call->setAttributes(fn->getAttributes());
return call;
}
}
#endif // LDC_GEN_IRSTATE_H
+128 -215
View File
@@ -393,19 +393,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op)
Type* t2 = rhs->getType()->toBasetype();
if (t->ty == Tstruct) {
if (!stripModifiers(t)->equals(stripModifiers(t2))) {
// FIXME: use 'rhs' for something !?!
DtoAggrZeroInit(lhs->getLVal());
#if DMDV2
TypeStruct *ts = static_cast<TypeStruct*>(lhs->getType());
if (ts->sym->isNested() && ts->sym->vthis)
DtoResolveNestedContext(loc, ts->sym, lhs->getLVal());
#endif
}
else {
DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
}
DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
}
else if (t->ty == Tarray) {
// lhs is slice
@@ -1013,6 +1001,110 @@ void DtoConstInitGlobal(VarDeclaration* vd)
/*////////////////////////////////////////////////////////////////////////////////////////
// DECLARATION EXP HELPER
////////////////////////////////////////////////////////////////////////////////////////*/
// TODO: Merge with DtoRawVarDeclaration!
void DtoVarDeclaration(VarDeclaration* vd)
{
assert(!vd->isDataseg() && "Statics/globals are handled in DtoDeclarationExp.");
assert(!vd->aliassym && "Aliases are handled in DtoDeclarationExp.");
Logger::println("vdtype = %s", vd->type->toChars());
#if DMDV2
if (vd->nestedrefs.dim)
#else
if (vd->nestedref)
#endif
{
Logger::println("has nestedref set (referenced by nested function/delegate)");
assert(vd->ir.irLocal && "irLocal is expected to be already set by DtoCreateNestedContext");
}
if(vd->ir.irLocal)
{
// Nothing to do if it has already been allocated.
}
#if DMDV2
/* Named Return Value Optimization (NRVO):
T f(){
T ret; // &ret == hidden pointer
ret = ...
return ret; // NRVO.
}
*/
else if (gIR->func()->retArg && gIR->func()->decl->nrvo_can && gIR->func()->decl->nrvo_var == vd) {
assert(!isSpecialRefVar(vd) && "Can this happen?");
vd->ir.irLocal = new IrLocal(vd);
vd->ir.irLocal->value = gIR->func()->retArg;
}
#endif
// normal stack variable, allocate storage on the stack if it has not already been done
else {
vd->ir.irLocal = new IrLocal(vd);
#if DMDV2
/* NRVO again:
T t = f(); // t's memory address is taken hidden pointer
*/
ExpInitializer *ei = 0;
if (vd->type->toBasetype()->ty == Tstruct && vd->init &&
!!(ei = vd->init->isExpInitializer()))
{
if (ei->exp->op == TOKconstruct) {
AssignExp *ae = static_cast<AssignExp*>(ei->exp);
if (ae->e2->op == TOKcall) {
CallExp *ce = static_cast<CallExp *>(ae->e2);
TypeFunction *tf = static_cast<TypeFunction *>(ce->e1->type->toBasetype());
if (tf->ty == Tfunction && tf->fty.arg_sret) {
LLValue* const val = ce->toElem(gIR)->getLVal();
if (isSpecialRefVar(vd))
{
vd->ir.irLocal->value = DtoAlloca(
vd->type->pointerTo(), vd->toChars());
DtoStore(val, vd->ir.irLocal->value);
}
else
{
vd->ir.irLocal->value = val;
}
goto Lexit;
}
}
}
}
#endif
Type* type = isSpecialRefVar(vd) ? vd->type->pointerTo() : vd->type;
LLType* lltype = DtoType(type);
llvm::Value* allocainst;
if(gTargetData->getTypeSizeInBits(lltype) == 0)
allocainst = llvm::ConstantPointerNull::get(getPtrToType(lltype));
else
allocainst = DtoAlloca(type, vd->toChars());
vd->ir.irLocal->value = allocainst;
DtoDwarfLocalVariable(allocainst, vd);
}
if (Logger::enabled())
Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
DtoInitializer(vd->ir.irLocal->value, vd->init); // TODO: Remove altogether?
#if DMDV2
Lexit:
/* Mark the point of construction of a variable that needs to be destructed.
*/
if (vd->edtor && !vd->noscope)
{
// Put vd on list of things needing destruction
gIR->varsInScope().push_back(vd);
}
#endif
}
DValue* DtoDeclarationExp(Dsymbol* declaration)
{
Logger::print("DtoDeclarationExp: %s\n", declaration->toChars());
@@ -1036,123 +1128,8 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
}
else
{
if (global.params.llvmAnnotate)
DtoAnnotation(declaration->toChars());
Logger::println("vdtype = %s", vd->type->toChars());
// ref vardecls are generated when DMD lowers foreach to a for statement,
// and this is a hack to support them for this case only
if(vd->isRef())
{
if (!vd->ir.irLocal)
vd->ir.irLocal = new IrLocal(vd);
ExpInitializer* ex = vd->init->isExpInitializer();
assert(ex && "ref vars must have expression initializer");
assert(ex->exp);
AssignExp* as = ex->exp->isAssignExp();
assert(as && "ref vars must be initialized by an assign exp");
DValue *val = as->e2->toElem(gIR);
if (val->isLVal())
{
vd->ir.irLocal->value = val->getLVal();
}
else
{
LLValue *newVal = DtoAlloca(val->type);
DtoStore(val->getRVal(), newVal);
vd->ir.irLocal->value = newVal;
}
}
// referenced by nested delegate?
#if DMDV2
if (vd->nestedrefs.dim) {
#else
if (vd->nestedref) {
#endif
Logger::println("has nestedref set");
assert(vd->ir.irLocal);
DtoNestedInit(vd);
// is it already allocated?
} else if(vd->ir.irLocal) {
// nothing to do...
}
#if DMDV2
/* Named Return Value Optimization (NRVO):
T f(){
T ret; // &ret == hidden pointer
ret = ...
return ret; // NRVO.
}
*/
else if (gIR->func()->retArg && gIR->func()->decl->nrvo_can && gIR->func()->decl->nrvo_var == vd) {
vd->ir.irLocal = new IrLocal(vd);
vd->ir.irLocal->value = gIR->func()->retArg;
}
#endif
// normal stack variable, allocate storage on the stack if it has not already been done
else if(!vd->isRef()) {
vd->ir.irLocal = new IrLocal(vd);
#if DMDV2
/* NRVO again:
T t = f(); // t's memory address is taken hidden pointer
*/
ExpInitializer *ei = 0;
if (vd->type->toBasetype()->ty == Tstruct && vd->init &&
!!(ei = vd->init->isExpInitializer()))
{
if (ei->exp->op == TOKconstruct) {
AssignExp *ae = static_cast<AssignExp*>(ei->exp);
if (ae->e2->op == TOKcall) {
CallExp *ce = static_cast<CallExp *>(ae->e2);
TypeFunction *tf = static_cast<TypeFunction *>(ce->e1->type->toBasetype());
if (tf->ty == Tfunction && tf->fty.arg_sret) {
vd->ir.irLocal->value = ce->toElem(gIR)->getLVal();
goto Lexit;
}
}
}
}
#endif
LLType* lltype = DtoType(vd->type);
llvm::Value* allocainst;
if(gTargetData->getTypeSizeInBits(lltype) == 0)
allocainst = llvm::ConstantPointerNull::get(getPtrToType(lltype));
else
allocainst = DtoAlloca(vd->type, vd->toChars());
//allocainst->setAlignment(vd->type->alignsize()); // TODO
vd->ir.irLocal->value = allocainst;
DtoDwarfLocalVariable(allocainst, vd);
}
else
{
assert(vd->ir.irLocal->value);
}
if (Logger::enabled())
Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
if (!vd->isRef())
DtoInitializer(vd->ir.irLocal->value, vd->init); // TODO: Remove altogether?
#if DMDV2
Lexit:
/* Mark the point of construction of a variable that needs to be destructed.
*/
if (vd->edtor && !vd->noscope)
{
// Put vd on list of things needing destruction
gIR->varsInScope().push_back(vd);
}
#endif
DtoVarDeclaration(vd);
}
return new DVarValue(vd->type, vd, vd->ir.getIrValue());
}
// struct declaration
@@ -1276,8 +1253,6 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr)
}
else
assert(!addr || addr == var->ir.irLocal->value);
DtoNestedInit(var);
}
// normal local variable
else
@@ -1461,7 +1436,7 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
TypeSArray* tsa = static_cast<TypeSArray*>(t);
dims.push_back(tsa->dim->toInteger());
assert(t->nextOf());
t = t->nextOf()->toBasetype();
t = stripModifiers(t->nextOf()->toBasetype());
}
size_t i = dims.size();
@@ -1482,8 +1457,8 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp)
{
#if DMDV2
Type* expbase = exp->type->toBasetype()->mutableOf()->merge();
Type* base = type->toBasetype()->mutableOf()->merge();
Type* expbase = stripModifiers(exp->type->toBasetype())->merge();
Type* base = stripModifiers(type->toBasetype())->merge();
#else
Type* expbase = exp->type->toBasetype();
Type* base = type->toBasetype();
@@ -1501,9 +1476,18 @@ LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp)
Logger::println("type is a static array, building constant array initializer to single value");
return expand_to_sarray(base, exp);
}
#if DMDV2
else if (base->ty == Tvector)
{
LLConstant* val = exp->toConstElem(gIR);
TypeVector* tv = (TypeVector*)base;
return llvm::ConstantVector::getSplat(tv->size(loc), val);
}
#endif
else
{
error("cannot yet convert default initializer %s of type %s to %s", exp->toChars(), exp->type->toChars(), type->toChars());
error(loc, "LDC internal error: cannot yet convert default initializer %s of type %s to %s",
exp->toChars(), exp->type->toChars(), type->toChars());
fatal();
}
assert(0);
@@ -1769,85 +1753,7 @@ Type * stripModifiers( Type * type )
#if DMDV2
if (type->ty == Tfunction)
return type;
Type *t = type;
while (t->mod)
{
switch (t->mod)
{
case MODconst:
t = type->cto;
break;
case MODshared:
t = type->sto;
break;
case MODimmutable:
t = type->ito;
break;
case MODshared | MODconst:
t = type->scto;
break;
case MODwild:
t = type->wto;
break;
case MODshared | MODwild:
t = type->swto;
break;
default:
assert(0 && "Unhandled type modifier");
}
if (!t)
{
unsigned sz = type->sizeTy[type->ty];
t = static_cast<Type *>(malloc(sz));
memcpy(t, type, sz);
t->mod = 0;
t->deco = NULL;
t->arrayof = NULL;
t->pto = NULL;
t->rto = NULL;
t->cto = NULL;
t->ito = NULL;
t->sto = NULL;
t->scto = NULL;
t->wto = NULL;
t->swto = NULL;
t->vtinfo = NULL;
t = t->merge();
t->fixTo(type);
switch (type->mod)
{
case MODconst:
t->cto = type;
break;
case MODimmutable:
t->ito = type;
break;
case MODshared:
t->sto = type;
break;
case MODshared | MODconst:
t->scto = type;
break;
case MODwild:
t->wto = type;
break;
case MODshared | MODwild:
t->swto = type;
break;
default:
assert(0);
}
}
}
return t;
return type->castMod(0);
#else
return type;
#endif
@@ -1895,7 +1801,7 @@ void callPostblit(Loc &loc, Expression *exp, LLValue *val)
{
Type *tb = exp->type->toBasetype();
if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar || exp->op == TOKthis) &&
if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar || exp->op == TOKthis || exp->op == TOKindex) &&
tb->ty == Tstruct)
{ StructDeclaration *sd = static_cast<TypeStruct *>(tb)->sym;
if (sd->postblit)
@@ -1914,6 +1820,13 @@ void callPostblit(Loc &loc, Expression *exp, LLValue *val)
//////////////////////////////////////////////////////////////////////////////////////////
bool isSpecialRefVar(VarDeclaration* vd)
{
return (vd->storage_class & STCref) && (vd->storage_class & STCforeach);
}
//////////////////////////////////////////////////////////////////////////////////////////
void printLabelName(std::ostream& target, const char* func_mangle, const char* label_name)
{
target << gTargetMachine->getMCAsmInfo()->getPrivateGlobalPrefix() <<

Some files were not shown because too many files have changed in this diff Show More