[svn r175] merged dmd 1.029

This commit is contained in:
Christian Kamm
2008-05-01 15:15:28 +02:00
parent 4cd137f9d4
commit 7ae4bc6477
27 changed files with 38673 additions and 38027 deletions

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -64,6 +64,8 @@ struct AggregateDeclaration : ScopeDsymbol
// 2: cannot determine size; fwd referenced // 2: cannot determine size; fwd referenced
int isdeprecated; // !=0 if deprecated int isdeprecated; // !=0 if deprecated
Scope *scope; // !=NULL means context to use Scope *scope; // !=NULL means context to use
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *dtor; // aggregate destructor
// Special member functions // Special member functions
InvariantDeclaration *inv; // invariant InvariantDeclaration *inv; // invariant
@@ -83,6 +85,7 @@ struct AggregateDeclaration : ScopeDsymbol
Type *getType(); Type *getType();
void addField(Scope *sc, VarDeclaration *v); void addField(Scope *sc, VarDeclaration *v);
int isDeprecated(); // is aggregate deprecated? int isDeprecated(); // is aggregate deprecated?
FuncDeclaration *buildDtor(Scope *sc);
void emitComment(Scope *sc); void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf); void toDocBuffer(OutBuffer *buf);
@@ -123,6 +126,7 @@ struct StructDeclaration : AggregateDeclaration
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle(); char *mangle();
char *kind(); char *kind();
Expression *cloneMembers();
void toDocBuffer(OutBuffer *buf); void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember PROT getAccess(Dsymbol *smember); // determine access to smember
@@ -164,7 +168,11 @@ struct BaseClass
void copyBaseInterfaces(BaseClasses *); void copyBaseInterfaces(BaseClasses *);
}; };
#if V2
#define CLASSINFO_SIZE (0x3C+16) // value of ClassInfo.size
#else
#define CLASSINFO_SIZE (0x3C+12) // value of ClassInfo.size #define CLASSINFO_SIZE (0x3C+12) // value of ClassInfo.size
#endif
struct ClassDeclaration : AggregateDeclaration struct ClassDeclaration : AggregateDeclaration
{ {
@@ -174,7 +182,6 @@ struct ClassDeclaration : AggregateDeclaration
ClassDeclaration *baseClass; // NULL only if this is Object ClassDeclaration *baseClass; // NULL only if this is Object
CtorDeclaration *ctor; CtorDeclaration *ctor;
CtorDeclaration *defaultCtor; // default constructor CtorDeclaration *defaultCtor; // default constructor
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *staticCtor; FuncDeclaration *staticCtor;
FuncDeclaration *staticDtor; FuncDeclaration *staticDtor;
Array vtbl; // Array of FuncDeclaration's making up the vtbl[] Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
@@ -191,13 +198,16 @@ struct ClassDeclaration : AggregateDeclaration
// their own vtbl[] // their own vtbl[]
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
int com; // !=0 if this is a COM class int com; // !=0 if this is a COM class (meaning
// it derives from IUnknown)
int isauto; // !=0 if this is an auto class int isauto; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class int isabstract; // !=0 if abstract class
int isnested; // !=0 if is nested int isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this class is nested VarDeclaration *vthis; // 'this' parameter if this class is nested
int inuse; // to prevent recursive attempts
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s); Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc); void semantic(Scope *sc);
@@ -208,11 +218,17 @@ struct ClassDeclaration : AggregateDeclaration
virtual int isBaseOf(ClassDeclaration *cd, int *poffset); virtual int isBaseOf(ClassDeclaration *cd, int *poffset);
Dsymbol *search(Loc, Identifier *ident, int flags); Dsymbol *search(Loc, Identifier *ident, int flags);
#if V2
int isFuncHidden(FuncDeclaration *fd);
#endif
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc); void interfaceSemantic(Scope *sc);
int isNested(); int isNested();
int isCOMclass(); int isCOMclass();
virtual int isCOMinterface(); virtual int isCOMinterface();
#if V2
virtual int isCPPinterface();
#endif
int isAbstract(); int isAbstract();
virtual int vtblOffset(); virtual int vtblOffset();
char *kind(); char *kind();
@@ -234,6 +250,7 @@ struct ClassDeclaration : AggregateDeclaration
Symbol *vtblsym; Symbol *vtblsym;
// llvm
void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
@@ -241,6 +258,9 @@ struct ClassDeclaration : AggregateDeclaration
struct InterfaceDeclaration : ClassDeclaration struct InterfaceDeclaration : ClassDeclaration
{ {
#if V2
int cpp; // !=0 if this is a C++ interface
#endif
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s); Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc); void semantic(Scope *sc);
@@ -248,6 +268,9 @@ struct InterfaceDeclaration : ClassDeclaration
int isBaseOf(BaseClass *bc, int *poffset); int isBaseOf(BaseClass *bc, int *poffset);
char *kind(); char *kind();
int vtblOffset(); int vtblOffset();
#if V2
int isCPPinterface();
#endif
virtual int isCOMinterface(); virtual int isCOMinterface();
void toObjFile(); // compile to .obj file void toObjFile(); // compile to .obj file

View File

@@ -203,15 +203,15 @@ int AttribDeclaration::cvMember(unsigned char *p)
if (d) if (d)
{ {
for (i = 0; i < d->dim; i++) for (i = 0; i < d->dim; i++)
{ Dsymbol *s; { Dsymbol *s;
s = (Dsymbol *)d->data[i]; s = (Dsymbol *)d->data[i];
n = s->cvMember(p); n = s->cvMember(p);
if (p) if (p)
p += n; p += n;
nwritten += n; nwritten += n;
} }
} }
return nwritten; return nwritten;
} }
@@ -917,6 +917,33 @@ void PragmaDeclaration::semantic(Scope *sc)
} }
} }
#endif #endif
else if (global.params.ignoreUnsupportedPragmas)
{
if (global.params.verbose)
{
/* Print unrecognized pragmas
*/
printf("pragma %s", ident->toChars());
if (args)
{
for (size_t i = 0; i < args->dim; i++)
{
Expression *e = (Expression *)args->data[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (i == 0)
printf(" (");
else
printf(",");
printf("%s", e->toChars());
}
if (args->dim)
printf(")");
}
printf("\n");
}
goto Lnodecl;
}
else else
error("unrecognized pragma(%s)", ident->toChars()); error("unrecognized pragma(%s)", ident->toChars());

View File

@@ -959,7 +959,8 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
Type *tb = t->toBasetype(); Type *tb = t->toBasetype();
if ((tb->ty == Tarray || tb->ty == Tsarray) && if ((tb->ty == Tarray || tb->ty == Tsarray) &&
(typeb->ty == Tarray || typeb->ty == Tsarray) && (typeb->ty == Tarray || typeb->ty == Tsarray) &&
tb->nextOf()->toBasetype()->ty != Tvoid) // Not trying to convert non-void[] to void[]
!(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid))
{ {
if (tb->ty == Tsarray) if (tb->ty == Tsarray)
{ TypeSArray *tsa = (TypeSArray *)tb; { TypeSArray *tsa = (TypeSArray *)tb;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -186,6 +186,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
isabstract = 0; isabstract = 0;
isnested = 0; isnested = 0;
vthis = NULL; vthis = NULL;
inuse = 0;
} }
Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
@@ -642,6 +643,7 @@ void ClassDeclaration::semantic(Scope *sc)
sizeok = 1; sizeok = 1;
Module::dprogress++; Module::dprogress++;
dtor = buildDtor(sc);
sc->pop(); sc->pop();
@@ -974,6 +976,8 @@ void InterfaceDeclaration::semantic(Scope *sc)
{ int i; { int i;
//printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
if (inuse)
return;
if (!scope) if (!scope)
{ type = type->semantic(loc, sc); { type = type->semantic(loc, sc);
handle = handle->semantic(loc, sc); handle = handle->semantic(loc, sc);
@@ -1058,7 +1062,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
baseclasses.remove(i); baseclasses.remove(i);
continue; continue;
} }
if (!b->base->symtab || b->base->scope) if (!b->base->symtab || b->base->scope || b->base->inuse)
{ {
//error("forward reference of base class %s", baseClass->toChars()); //error("forward reference of base class %s", baseClass->toChars());
// Forward reference of base, try again later // Forward reference of base, try again later
@@ -1123,11 +1127,13 @@ void InterfaceDeclaration::semantic(Scope *sc)
sc->structalign = 8; sc->structalign = 8;
structalign = sc->structalign; structalign = sc->structalign;
sc->offset = 8; sc->offset = 8;
inuse++;
for (i = 0; i < members->dim; i++) for (i = 0; i < members->dim; i++)
{ {
Dsymbol *s = (Dsymbol *)members->data[i]; Dsymbol *s = (Dsymbol *)members->data[i];
s->semantic(sc); s->semantic(sc);
} }
inuse--;
//members->print(); //members->print();
sc->pop(); sc->pop();
//printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);

175
dmd/clone.c Normal file
View File

@@ -0,0 +1,175 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "root.h"
#include "aggregate.h"
#include "scope.h"
#include "mtype.h"
#include "declaration.h"
#include "module.h"
#include "id.h"
#include "expression.h"
#include "statement.h"
/*********************************
* Generate expression that calls opClone()
* for each member of the struct
* (can be NULL for members that don't need one)
*/
#if V2
Expression *StructDeclaration::cloneMembers()
{
Expression *e = NULL;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
Type *tv = v->type->toBasetype();
size_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->opclone)
{ Expression *ex;
// this.v
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
{ // this.v.opClone()
ex = new DotVarExp(0, ex, sd->opclone, 0);
ex = new CallExp(0, ex);
}
else
{
// _callOpClones(&this.v, opclone, dim)
Expressions *args = new Expressions();
args->push(new AddrExp(0, ex));
args->push(new SymOffExp(0, sd->opclone, 0));
args->push(new IntegerExp(dim));
FuncDeclaration *ec = FuncDeclaration::genCfunc(Type::tvoid, "_callOpClones");
ex = new CallExp(0, new VarExp(0, ec), args);
}
e = Expression::combine(e, ex);
}
}
}
return e;
}
#endif
/*****************************************
* Create inclusive destructor for struct by aggregating
* all the destructors in dtors[] with the destructors for
* all the members.
*/
FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
{
//printf("StructDeclaration::buildDtor() %s\n", toChars());
Expression *e = NULL;
#if V2
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
Type *tv = v->type->toBasetype();
size_t dim = 1;
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
dim *= ((TypeSArray *)tv)->dim->toInteger();
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->dtor)
{ Expression *ex;
// this.v
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
if (dim == 1)
{ // this.v.dtor()
ex = new DotVarExp(0, ex, sd->dtor, 0);
ex = new CallExp(0, ex);
}
else
{
// Typeinfo.destroy(cast(void*)&this.v);
Expression *ea = new AddrExp(0, ex);
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
Expressions *args = new Expressions();
args->push(ea);
Expression *et = v->type->getTypeInfo(sc);
et = new DotIdExp(0, et, Id::destroy);
ex = new CallExp(0, et, args);
}
e = Expression::combine(ex, e); // combine in reverse order
}
}
}
/* Build our own "destructor" which executes e
*/
if (e)
{ //printf("Building __fieldDtor()\n");
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
dd->fbody = new ExpStatement(0, e);
dtors.shift(dd);
members->push(dd);
dd->semantic(sc);
}
#endif
switch (dtors.dim)
{
case 0:
return NULL;
case 1:
return (FuncDeclaration *)dtors.data[0];
default:
e = NULL;
for (size_t i = 0; i < dtors.dim; i++)
{ FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd);
ex = new CallExp(0, ex);
e = Expression::combine(ex, e);
}
DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
dd->fbody = new ExpStatement(0, e);
members->push(dd);
dd->semantic(sc);
return dd;
}
}

View File

@@ -667,6 +667,7 @@ void VarDeclaration::semantic(Scope *sc)
size_t nelems = Argument::dim(tt->arguments); size_t nelems = Argument::dim(tt->arguments);
Objects *exps = new Objects(); Objects *exps = new Objects();
exps->setDim(nelems); exps->setDim(nelems);
Expression *ie = init ? init->toExpression() : NULL;
for (size_t i = 0; i < nelems; i++) for (size_t i = 0; i < nelems; i++)
{ Argument *arg = Argument::getNth(tt->arguments, i); { Argument *arg = Argument::getNth(tt->arguments, i);
@@ -677,7 +678,16 @@ void VarDeclaration::semantic(Scope *sc)
char *name = (char *)buf.extractData(); char *name = (char *)buf.extractData();
Identifier *id = new Identifier(name, TOKidentifier); Identifier *id = new Identifier(name, TOKidentifier);
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL); Expression *einit = ie;
if (ie && ie->op == TOKtuple)
{ einit = (Expression *)((TupleExp *)ie)->exps->data[i];
}
Initializer *ti = init;
if (einit)
{ ti = new ExpInitializer(einit->loc, einit);
}
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
v->semantic(sc); v->semantic(sc);
@@ -1109,8 +1119,8 @@ Expression *VarDeclaration::callAutoDtor()
* classes to determine if there's no way the monitor * classes to determine if there's no way the monitor
* could be set. * could be set.
*/ */
if (cd->isInterfaceDeclaration()) //if (cd->isInterfaceDeclaration())
error("interface %s cannot be scope", cd->toChars()); //error("interface %s cannot be scope", cd->toChars());
if (1 || onstack || cd->dtors.dim) // if any destructors if (1 || onstack || cd->dtors.dim) // if any destructors
{ {
// delete this; // delete this;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -33,6 +33,7 @@ struct ExpInitializer;
struct StructDeclaration; struct StructDeclaration;
struct TupleType; struct TupleType;
struct InterState; struct InterState;
struct IRState;
enum PROT; enum PROT;
enum LINK; enum LINK;
@@ -64,6 +65,12 @@ enum STC
STCscope = 0x80000, // template parameter STCscope = 0x80000, // template parameter
STCinvariant = 0x100000, STCinvariant = 0x100000,
STCref = 0x200000, STCref = 0x200000,
STCinit = 0x400000, // has explicit initializer
STCmanifest = 0x800000, // manifest constant
STCnodtor = 0x1000000, // don't run destructor
STCnothrow = 0x2000000, // never throws exceptions
STCpure = 0x4000000, // pure function
STCtls = 0x8000000, // thread local
}; };
struct Match struct Match
@@ -94,6 +101,7 @@ struct Declaration : Dsymbol
void semantic(Scope *sc); void semantic(Scope *sc);
char *kind(); char *kind();
unsigned size(Loc loc); unsigned size(Loc loc);
void checkModify(Loc loc, Scope *sc, Type *t);
void emitComment(Scope *sc); void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf); void toDocBuffer(OutBuffer *buf);
@@ -125,6 +133,7 @@ struct Declaration : Dsymbol
Declaration *isDeclaration() { return this; } Declaration *isDeclaration() { return this; }
// llvm
virtual void toObjFile(); // compile to .obj file virtual void toObjFile(); // compile to .obj file
}; };
@@ -517,13 +526,14 @@ struct FuncDeclaration : Declaration
int inlineNest; // !=0 if nested inline int inlineNest; // !=0 if nested inline
int cantInterpret; // !=0 if cannot interpret function int cantInterpret; // !=0 if cannot interpret function
int semanticRun; // !=0 if semantic3() had been run int semanticRun; // !=0 if semantic3() had been run
// this function's frame ptr
ForeachStatement *fes; // if foreach body, this is the foreach ForeachStatement *fes; // if foreach body, this is the foreach
int introducing; // !=0 if 'introducing' function int introducing; // !=0 if 'introducing' function
Type *tintro; // if !=NULL, then this is the type Type *tintro; // if !=NULL, then this is the type
// of the 'introducing' function // of the 'introducing' function
// this one is overriding // this one is overriding
int inferRetType; // !=0 if return type is to be inferred int inferRetType; // !=0 if return type is to be inferred
Scope *scope; // !=NULL means context to use Scope *scope; // !=NULL means context to use
// Things that should really go into Scope // Things that should really go into Scope
int hasReturnExp; // 1 if there's a return exp; statement int hasReturnExp; // 1 if there's a return exp; statement
@@ -558,6 +568,7 @@ struct FuncDeclaration : Declaration
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs); void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
int overrides(FuncDeclaration *fd); int overrides(FuncDeclaration *fd);
int findVtblIndex(Array *vtbl, int dim);
int overloadInsert(Dsymbol *s); int overloadInsert(Dsymbol *s);
FuncDeclaration *overloadExactMatch(Type *t); FuncDeclaration *overloadExactMatch(Type *t);
FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments); FuncDeclaration *overloadResolve(Loc loc, Expressions *arguments);
@@ -648,6 +659,7 @@ struct CtorDeclaration : FuncDeclaration
struct DtorDeclaration : FuncDeclaration struct DtorDeclaration : FuncDeclaration
{ {
DtorDeclaration(Loc loc, Loc endloc); DtorDeclaration(Loc loc, Loc endloc);
DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *); Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc); void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -102,6 +102,7 @@ int isDitto(unsigned char *comment);
unsigned char *skipwhitespace(unsigned char *p); unsigned char *skipwhitespace(unsigned char *p);
unsigned skiptoident(OutBuffer *buf, unsigned i); unsigned skiptoident(OutBuffer *buf, unsigned i);
unsigned skippastident(OutBuffer *buf, unsigned i); unsigned skippastident(OutBuffer *buf, unsigned i);
unsigned skippastURL(OutBuffer *buf, unsigned i);
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset); void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
@@ -114,7 +115,7 @@ DDOC = <html><head>\n\
</head><body>\n\ </head><body>\n\
<h1>$(TITLE)</h1>\n\ <h1>$(TITLE)</h1>\n\
$(BODY)\n\ $(BODY)\n\
<hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/ddoc.html, Ddoc). $(COPYRIGHT))\n\ <hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/1.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\
</body></html>\n\ </body></html>\n\
\n\ \n\
B = <b>$0</b>\n\ B = <b>$0</b>\n\
@@ -371,14 +372,26 @@ void Module::gendocfile()
void Dsymbol::emitDitto(Scope *sc) void Dsymbol::emitDitto(Scope *sc)
{ {
//printf("Dsymbol::emitDitto() %s %s\n", kind(), toChars());
OutBuffer *buf = sc->docbuf; OutBuffer *buf = sc->docbuf;
unsigned o; unsigned o;
OutBuffer b; OutBuffer b;
b.writestring("$(DDOC_DITTO "); b.writestring("$(DDOC_DITTO ");
o = b.offset; o = b.offset;
toDocBuffer(&b); toDocBuffer(&b);
highlightCode(sc, this, &b, o); //printf("b: '%.*s'\n", b.offset, b.data);
/* If 'this' is a function template, then highlightCode() was
* already run by FuncDeclaration::toDocbuffer().
*/
TemplateDeclaration *td;
if (parent &&
(td = parent->isTemplateDeclaration()) != NULL &&
td->onemember == this)
{
}
else
highlightCode(sc, this, &b, o);
b.writeByte(')'); b.writeByte(')');
buf->spread(sc->lastoffset, b.offset); buf->spread(sc->lastoffset, b.offset);
memcpy(buf->data + sc->lastoffset, b.data, b.offset); memcpy(buf->data + sc->lastoffset, b.data, b.offset);
@@ -435,6 +448,7 @@ void emitProtection(OutBuffer *buf, PROT prot)
void Dsymbol::emitComment(Scope *sc) { } void Dsymbol::emitComment(Scope *sc) { }
void InvariantDeclaration::emitComment(Scope *sc) { } void InvariantDeclaration::emitComment(Scope *sc) { }
//void PostBlitDeclaration::emitComment(Scope *sc) { }
void DtorDeclaration::emitComment(Scope *sc) { } void DtorDeclaration::emitComment(Scope *sc) { }
void StaticCtorDeclaration::emitComment(Scope *sc) { } void StaticCtorDeclaration::emitComment(Scope *sc) { }
void StaticDtorDeclaration::emitComment(Scope *sc) { } void StaticDtorDeclaration::emitComment(Scope *sc) { }
@@ -635,6 +649,7 @@ void Dsymbol::toDocBuffer(OutBuffer *buf)
//printf("Dsymbol::toDocbuffer() %s\n", toChars()); //printf("Dsymbol::toDocbuffer() %s\n", toChars());
HdrGenState hgs; HdrGenState hgs;
hgs.ddoc = 1;
toCBuffer(buf, &hgs); toCBuffer(buf, &hgs);
} }
@@ -738,9 +753,9 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
buf->writeByte(' '); buf->writeByte(' ');
buf->writestring(ident->toChars()); buf->writestring(ident->toChars());
buf->writeByte('('); buf->writeByte('(');
for (int i = 0; i < td->parameters->dim; i++) for (int i = 0; i < td->origParameters->dim; i++)
{ {
TemplateParameter *tp = (TemplateParameter *)td->parameters->data[i]; TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
if (i) if (i)
buf->writeByte(','); buf->writeByte(',');
tp->toCBuffer(buf, &hgs); tp->toCBuffer(buf, &hgs);
@@ -1491,6 +1506,55 @@ unsigned skippastident(OutBuffer *buf, unsigned i)
} }
/************************************************
* Scan forward past URL starting at i.
* We don't want to highlight parts of a URL.
* Returns:
* i if not a URL
* index just past it if it is a URL
*/
unsigned skippastURL(OutBuffer *buf, unsigned i)
{ unsigned length = buf->offset - i;
unsigned char *p = &buf->data[i];
unsigned j;
unsigned sawdot = 0;
if (length > 7 && memicmp((char *)p, "http://", 7) == 0)
{
j = 7;
}
else if (length > 8 && memicmp((char *)p, "https://", 8) == 0)
{
j = 8;
}
else
goto Lno;
for (; j < length; j++)
{ unsigned char c = p[j];
if (isalnum(c))
continue;
if (c == '-' || c == '_' || c == '?' ||
c == '=' || c == '%' || c == '&' ||
c == '/' || c == '+' || c == '#' ||
c == '~')
continue;
if (c == '.')
{
sawdot = 1;
continue;
}
break;
}
if (sawdot)
return i + j;
Lno:
return i;
}
/**************************************************** /****************************************************
*/ */
@@ -1735,6 +1799,12 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
j = skippastident(buf, i); j = skippastident(buf, i);
if (j > i) if (j > i)
{ {
unsigned k = skippastURL(buf, i);
if (k > i)
{ i = k - 1;
break;
}
if (buf->data[i] == '_') // leading '_' means no highlight if (buf->data[i] == '_') // leading '_' means no highlight
{ {
buf->remove(i, 1); buf->remove(i, 1);

View File

@@ -94,6 +94,7 @@ enum PROT
PROTexport, PROTexport,
}; };
struct Dsymbol : Object struct Dsymbol : Object
{ {
Identifier *ident; Identifier *ident;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -89,6 +89,7 @@ enum PREC precedence[TOKMAX];
void initPrecedence() void initPrecedence()
{ {
precedence[TOKdotvar] = PREC_primary;
precedence[TOKimport] = PREC_primary; precedence[TOKimport] = PREC_primary;
precedence[TOKidentifier] = PREC_primary; precedence[TOKidentifier] = PREC_primary;
precedence[TOKthis] = PREC_primary; precedence[TOKthis] = PREC_primary;
@@ -170,6 +171,8 @@ void initPrecedence()
precedence[TOKquestion] = PREC_cond; precedence[TOKquestion] = PREC_cond;
precedence[TOKassign] = PREC_assign; precedence[TOKassign] = PREC_assign;
precedence[TOKconstruct] = PREC_assign;
precedence[TOKblit] = PREC_assign;
precedence[TOKaddass] = PREC_assign; precedence[TOKaddass] = PREC_assign;
precedence[TOKminass] = PREC_assign; precedence[TOKminass] = PREC_assign;
precedence[TOKcatass] = PREC_assign; precedence[TOKcatass] = PREC_assign;
@@ -645,7 +648,7 @@ void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *h
if (i) if (i)
buf->writeByte(','); buf->writeByte(',');
argbuf.reset(); argbuf.reset();
arg->type->toCBuffer2(&argbuf, NULL, hgs); arg->type->toCBuffer2(&argbuf, hgs, 0);
buf->write(&argbuf); buf->write(&argbuf);
} }
} }
@@ -2496,6 +2499,8 @@ Expression *ArrayLiteralExp::semantic(Scope *sc)
#if LOGSEMANTIC #if LOGSEMANTIC
printf("ArrayLiteralExp::semantic('%s')\n", toChars()); printf("ArrayLiteralExp::semantic('%s')\n", toChars());
#endif #endif
if (type)
return this;
// Run semantic() on each element // Run semantic() on each element
for (int i = 0; i < elements->dim; i++) for (int i = 0; i < elements->dim; i++)
@@ -4408,6 +4413,8 @@ int BinExp::checkSideEffect(int flag)
if (op == TOKplusplus || if (op == TOKplusplus ||
op == TOKminusminus || op == TOKminusminus ||
op == TOKassign || op == TOKassign ||
op == TOKconstruct ||
op == TOKblit ||
op == TOKaddass || op == TOKaddass ||
op == TOKminass || op == TOKminass ||
op == TOKcatass || op == TOKcatass ||
@@ -4995,6 +5002,7 @@ Expression *DotVarExp::semantic(Scope *sc)
if (s && s->isClassDeclaration()) if (s && s->isClassDeclaration())
e1->type = s->isClassDeclaration()->type; e1->type = s->isClassDeclaration()->type;
e1 = e1->semantic(sc);
goto L1; goto L1;
} }
#ifdef DEBUG #ifdef DEBUG
@@ -6135,13 +6143,10 @@ Expression *DeleteExp::semantic(Scope *sc)
if (f) if (f)
{ {
Expression *e;
Expression *ec;
Type *tpv = Type::tvoid->pointerTo(); Type *tpv = Type::tvoid->pointerTo();
e = e1; Expression *e = e1->castTo(sc, tpv);
e->type = tpv; Expression *ec = new VarExp(loc, f);
ec = new VarExp(loc, f);
e = new CallExp(loc, ec, e); e = new CallExp(loc, ec, e);
return e->semantic(sc); return e->semantic(sc);
} }
@@ -6233,7 +6238,10 @@ Expression *CastExp::semantic(Scope *sc)
} }
Type *tob = to->toBasetype(); Type *tob = to->toBasetype();
if (tob->ty == Tstruct && !tob->equals(e1->type->toBasetype())) if (tob->ty == Tstruct &&
!tob->equals(e1->type->toBasetype()) &&
((TypeStruct *)to)->sym->search(0, Id::call, 0)
)
{ {
/* Look to replace: /* Look to replace:
* cast(S)t * cast(S)t
@@ -7272,6 +7280,8 @@ Expression *CatAssignExp::semantic(Scope *sc)
Type *tb1 = e1->type->toBasetype(); Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype(); Type *tb2 = e2->type->toBasetype();
e2->rvalue();
if ((tb1->ty == Tarray) && if ((tb1->ty == Tarray) &&
(tb2->ty == Tarray || tb2->ty == Tsarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) &&
e2->implicitConvTo(e1->type) e2->implicitConvTo(e1->type)
@@ -8339,6 +8349,13 @@ Expression *CmpExp::semantic(Scope *sc)
return this; return this;
BinExp::semanticp(sc); BinExp::semanticp(sc);
if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
{
error("do not use null when comparing class types");
}
e = op_overload(sc); e = op_overload(sc);
if (e) if (e)
{ {
@@ -8392,6 +8409,7 @@ int CmpExp::isBit()
EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, op, sizeof(EqualExp), e1, e2) : BinExp(loc, op, sizeof(EqualExp), e1, e2)
{ {
assert(op == TOKequal || op == TOKnotequal);
} }
Expression *EqualExp::semantic(Scope *sc) Expression *EqualExp::semantic(Scope *sc)
@@ -8426,6 +8444,14 @@ Expression *EqualExp::semantic(Scope *sc)
} }
} }
if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
{
error("use '%s' instead of '%s' when comparing with null",
Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
Token::toChars(op));
}
//if (e2->op != TOKnull) //if (e2->op != TOKnull)
{ {
e = op_overload(sc); e = op_overload(sc);

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -35,6 +35,7 @@
FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type) FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type)
: Declaration(id) : Declaration(id)
{ {
//printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
this->storage_class = storage_class; this->storage_class = storage_class;
this->type = type; this->type = type;
this->loc = loc; this->loc = loc;
@@ -262,117 +263,155 @@ void FuncDeclaration::semantic(Scope *sc)
} }
// Find index of existing function in vtbl[] to override // Find index of existing function in vtbl[] to override
if (cd->baseClass) vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0);
switch (vi)
{ {
for (vi = 0; vi < cd->baseClass->vtbl.dim; vi++) case -1: // didn't find one
{ // This is an 'introducing' function.
FuncDeclaration *fdv = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration();
// BUG: should give error if argument types match, // Verify this doesn't override previous final function
// but return type does not? if (cd->baseClass)
{ Dsymbol *s = cd->baseClass->search(loc, ident, 0);
//printf("\tvtbl[%d] = '%s'\n", vi, fdv ? fdv->ident->toChars() : ""); if (s)
if (fdv && fdv->ident == ident)
{
int cov = type->covariant(fdv->type);
//printf("\tbaseclass cov = %d\n", cov);
if (cov == 2)
{ {
//type->print(); FuncDeclaration *f = s->isFuncDeclaration();
//fdv->type->print(); f = f->overloadExactMatch(type);
//printf("%s %s\n", type->deco, fdv->type->deco); if (f && f->isFinal() && f->prot() != PROTprivate)
error("of type %s overrides but is not covariant with %s of type %s", error("cannot override final function %s", f->toPrettyChars());
type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
}
if (cov == 1)
{
if (fdv->isFinal())
error("cannot override final function %s", fdv->toPrettyChars());
if (fdv->toParent() == parent)
{
// If both are mixins, then error.
// If either is not, the one that is not overrides
// the other.
if (fdv->parent->isClassDeclaration())
goto L1;
if (!this->parent->isClassDeclaration()
#if !BREAKABI
&& !isDtorDeclaration()
#endif
)
error("multiple overrides of same function");
}
cd->vtbl.data[vi] = (void *)this;
vtblIndex = vi;
/* This works by whenever this function is called,
* it actually returns tintro, which gets dynamically
* cast to type. But we know that tintro is a base
* of type, so we could optimize it by not doing a
* dynamic cast, but just subtracting the isBaseOf()
* offset if the value is != null.
*/
if (fdv->tintro)
tintro = fdv->tintro;
else if (!type->equals(fdv->type))
{
/* Only need to have a tintro if the vptr
* offsets differ
*/
int offset;
if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
{
tintro = fdv->type;
}
}
goto L1;
}
if (cov == 3)
{
cd->sizeok = 2; // can't finish due to forward reference
return;
} }
} }
if (isFinal())
{
cd->vtblFinal.push(this);
}
else
{
// Append to end of vtbl[]
//printf("\tintroducing function\n");
introducing = 1;
vi = cd->vtbl.dim;
cd->vtbl.push(this);
vtblIndex = vi;
}
break;
case -2: // can't determine because of fwd refs
cd->sizeok = 2; // can't finish due to forward reference
return;
default:
{ FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi];
// This function is covariant with fdv
if (fdv->isFinal())
error("cannot override final function %s", fdv->toPrettyChars());
#if V2
if (!isOverride() && global.params.warnings)
error("overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
#endif
if (fdv->toParent() == parent)
{
// If both are mixins, then error.
// If either is not, the one that is not overrides
// the other.
if (fdv->parent->isClassDeclaration())
break;
if (!this->parent->isClassDeclaration()
#if !BREAKABI
&& !isDtorDeclaration()
#endif
#if V2
&& !isPostBlitDeclaration()
#endif
)
error("multiple overrides of same function");
}
cd->vtbl.data[vi] = (void *)this;
vtblIndex = vi;
/* This works by whenever this function is called,
* it actually returns tintro, which gets dynamically
* cast to type. But we know that tintro is a base
* of type, so we could optimize it by not doing a
* dynamic cast, but just subtracting the isBaseOf()
* offset if the value is != null.
*/
if (fdv->tintro)
tintro = fdv->tintro;
else if (!type->equals(fdv->type))
{
/* Only need to have a tintro if the vptr
* offsets differ
*/
int offset;
if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
{
tintro = fdv->type;
}
}
break;
} }
} }
// This is an 'introducing' function.
// Verify this doesn't override previous final function
if (cd->baseClass)
{ Dsymbol *s = cd->baseClass->search(loc, ident, 0);
if (s)
{
FuncDeclaration *f = s->isFuncDeclaration();
f = f->overloadExactMatch(type);
if (f && f->isFinal() && f->prot() != PROTprivate)
error("cannot override final function %s", f->toPrettyChars());
}
}
if (isFinal())
{
cd->vtblFinal.push(this);
}
else
{
// Append to end of vtbl[]
//printf("\tintroducing function\n");
introducing = 1;
vi = cd->vtbl.dim;
cd->vtbl.push(this);
vtblIndex = vi;
}
L1: ;
/* Go through all the interface bases. /* Go through all the interface bases.
* If this function is covariant with any members of those interface * If this function is covariant with any members of those interface
* functions, set the tintro. * functions, set the tintro.
*/ */
for (int i = 0; i < cd->interfaces_dim; i++) for (int i = 0; i < cd->interfaces_dim; i++)
{ {
#if 1
BaseClass *b = cd->interfaces[i];
vi = findVtblIndex(&b->base->vtbl, b->base->vtbl.dim);
switch (vi)
{
case -1:
break;
case -2:
cd->sizeok = 2; // can't finish due to forward reference
return;
default:
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
Type *ti = NULL;
if (fdv->tintro)
ti = fdv->tintro;
else if (!type->equals(fdv->type))
{
/* Only need to have a tintro if the vptr
* offsets differ
*/
int offset;
if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
{
ti = fdv->type;
#if 0
if (offset)
ti = fdv->type;
else if (type->nextOf()->ty == Tclass)
{ ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
if (cdn && cdn->sizeok != 1)
ti = fdv->type;
}
#endif
}
}
if (ti)
{
if (tintro && !tintro->equals(ti))
{
error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
}
tintro = ti;
}
goto L2;
}
}
#else
BaseClass *b = cd->interfaces[i]; BaseClass *b = cd->interfaces[i];
for (vi = 0; vi < b->base->vtbl.dim; vi++) for (vi = 0; vi < b->base->vtbl.dim; vi++)
{ {
@@ -433,11 +472,12 @@ void FuncDeclaration::semantic(Scope *sc)
} }
} }
} }
#endif
} }
if (introducing && isOverride()) if (introducing && isOverride())
{ {
error("function %s does not override any", toChars()); error("does not override any function");
} }
L2: ; L2: ;
@@ -557,10 +597,10 @@ void FuncDeclaration::semantic3(Scope *sc)
{ {
if (global.errors) if (global.errors)
return; return;
printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
assert(0); assert(0);
} }
//printf("FuncDeclaration::semantic3('%s.%s', sc = %p)\n", parent->toChars(), toChars(), sc); //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
//fflush(stdout); //fflush(stdout);
//{ static int x; if (++x == 2) *(char*)0=0; } //{ static int x; if (++x == 2) *(char*)0=0; }
//printf("\tlinkage = %d\n", sc->linkage); //printf("\tlinkage = %d\n", sc->linkage);
@@ -591,15 +631,15 @@ void FuncDeclaration::semantic3(Scope *sc)
if (fbody || frequire) if (fbody || frequire)
{ {
// Establish function scope /* Symbol table into which we place parameters and nested functions,
ScopeDsymbol *ss; * solely to diagnose name collisions.
Scope *sc2; */
localsymtab = new DsymbolTable(); localsymtab = new DsymbolTable();
ss = new ScopeDsymbol(); // Establish function scope
ScopeDsymbol *ss = new ScopeDsymbol();
ss->parent = sc->scopesym; ss->parent = sc->scopesym;
sc2 = sc->push(ss); Scope *sc2 = sc->push(ss);
sc2->func = this; sc2->func = this;
sc2->parent = this; sc2->parent = this;
sc2->callSuper = 0; sc2->callSuper = 0;
@@ -608,7 +648,7 @@ void FuncDeclaration::semantic3(Scope *sc)
sc2->sw = NULL; sc2->sw = NULL;
sc2->fes = fes; sc2->fes = fes;
sc2->linkage = LINKd; sc2->linkage = LINKd;
sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated); sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCfinal);
sc2->protection = PROTpublic; sc2->protection = PROTpublic;
sc2->explicitProtection = 0; sc2->explicitProtection = 0;
sc2->structalign = 8; sc2->structalign = 8;
@@ -693,7 +733,7 @@ void FuncDeclaration::semantic3(Scope *sc)
} }
} }
// Propagate storage class from tuple arguments to their sub-arguments. // Propagate storage class from tuple parameters to their element-parameters.
if (f->parameters) if (f->parameters)
{ {
for (size_t i = 0; i < f->parameters->dim; i++) for (size_t i = 0; i < f->parameters->dim; i++)
@@ -712,8 +752,9 @@ void FuncDeclaration::semantic3(Scope *sc)
// Declare all the function parameters as variables // Declare all the function parameters as variables
if (nparams) if (nparams)
{ // parameters[] has all the tuples removed, as the back end { /* parameters[] has all the tuples removed, as the back end
// doesn't know about tuples * doesn't know about tuples
*/
parameters = new Dsymbols(); parameters = new Dsymbols();
parameters->reserve(nparams); parameters->reserve(nparams);
for (size_t i = 0; i < nparams; i++) for (size_t i = 0; i < nparams; i++)
@@ -722,14 +763,16 @@ void FuncDeclaration::semantic3(Scope *sc)
Identifier *id = arg->ident; Identifier *id = arg->ident;
if (!id) if (!id)
{ {
//error("no identifier for parameter %d of %s", i + 1, toChars()); /* Generate identifier for un-named parameter,
* because we need it later on.
*/
OutBuffer buf; OutBuffer buf;
buf.printf("_param_%zu", i); buf.printf("_param_%zu", i);
char *name = (char *)buf.extractData(); char *name = (char *)buf.extractData();
id = new Identifier(name, TOKidentifier); id = new Identifier(name, TOKidentifier);
arg->ident = id; arg->ident = id;
} }
VarDeclaration *v = new VarDeclaration(0, arg->type, id, NULL); VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
v->storage_class |= STCparameter; v->storage_class |= STCparameter;
if (f->varargs == 2 && i + 1 == nparams) if (f->varargs == 2 && i + 1 == nparams)
@@ -783,10 +826,14 @@ void FuncDeclaration::semantic3(Scope *sc)
} }
} }
/* Do the semantic analysis on the [in] preconditions and
* [out] postconditions.
*/
sc2->incontract++; sc2->incontract++;
if (frequire) if (frequire)
{ { /* frequire is composed of the [in] contracts
*/
// BUG: need to error if accessing out parameters // BUG: need to error if accessing out parameters
// BUG: need to treat parameters as const // BUG: need to treat parameters as const
// BUG: need to disallow returns and throws // BUG: need to disallow returns and throws
@@ -796,10 +843,9 @@ void FuncDeclaration::semantic3(Scope *sc)
} }
if (fensure || addPostInvariant()) if (fensure || addPostInvariant())
{ { /* fensure is composed of the [out] contracts
ScopeDsymbol *sym; */
ScopeDsymbol *sym = new ScopeDsymbol();
sym = new ScopeDsymbol();
sym->parent = sc2->scopesym; sym->parent = sc2->scopesym;
sc2 = sc2->push(sym); sc2 = sc2->push(sym);
@@ -903,6 +949,8 @@ void FuncDeclaration::semantic3(Scope *sc)
if (fbody) if (fbody)
{ ClassDeclaration *cd = isClassMember(); { ClassDeclaration *cd = isClassMember();
/* If this is a class constructor
*/
if (isCtorDeclaration() && cd) if (isCtorDeclaration() && cd)
{ {
for (int i = 0; i < cd->fields.dim; i++) for (int i = 0; i < cd->fields.dim; i++)
@@ -921,7 +969,7 @@ void FuncDeclaration::semantic3(Scope *sc)
{ // If no return type inferred yet, then infer a void { // If no return type inferred yet, then infer a void
if (!type->nextOf()) if (!type->nextOf())
{ {
type->next = Type::tvoid; ((TypeFunction *)type)->next = Type::tvoid;
type = type->semantic(loc, sc); type = type->semantic(loc, sc);
} }
f = (TypeFunction *)type; f = (TypeFunction *)type;
@@ -1042,9 +1090,8 @@ void FuncDeclaration::semantic3(Scope *sc)
// Merge in initialization of 'out' parameters // Merge in initialization of 'out' parameters
if (parameters) if (parameters)
{ for (size_t i = 0; i < parameters->dim; i++) { for (size_t i = 0; i < parameters->dim; i++)
{ VarDeclaration *v; {
VarDeclaration *v = (VarDeclaration *)parameters->data[i];
v = (VarDeclaration *)parameters->data[i];
if (v->storage_class & STCout) if (v->storage_class & STCout)
{ {
assert(v->init); assert(v->init);
@@ -1255,6 +1302,50 @@ int FuncDeclaration::overrides(FuncDeclaration *fd)
return result; return result;
} }
/*************************************************
* Find index of function in vtbl[0..dim] that
* this function overrides.
* Returns:
* -1 didn't find one
* -2 can't determine because of forward references
*/
int FuncDeclaration::findVtblIndex(Array *vtbl, int dim)
{
for (int vi = 0; vi < dim; vi++)
{
FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration();
if (fdv && fdv->ident == ident)
{
int cov = type->covariant(fdv->type);
//printf("\tbaseclass cov = %d\n", cov);
switch (cov)
{
case 0: // types are distinct
break;
case 1:
return vi;
case 2:
//type->print();
//fdv->type->print();
//printf("%s %s\n", type->deco, fdv->type->deco);
error("of type %s overrides but is not covariant with %s of type %s",
type->toChars(), fdv->toPrettyChars(), fdv->type->toChars());
break;
case 3:
return -2; // forward references
default:
assert(0);
}
}
}
return -1;
}
/**************************************************** /****************************************************
* Overload this FuncDeclaration with the new one f. * Overload this FuncDeclaration with the new one f.
* Return !=0 if successful; i.e. no conflict. * Return !=0 if successful; i.e. no conflict.
@@ -1684,6 +1775,11 @@ LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
} }
return (LabelDsymbol *)s; return (LabelDsymbol *)s;
} }
/****************************************
* If non-static member function that has a 'this' pointer,
* return the aggregate it is a member of.
* Otherwise, return NULL.
*/
AggregateDeclaration *FuncDeclaration::isThis() AggregateDeclaration *FuncDeclaration::isThis()
{ AggregateDeclaration *ad; { AggregateDeclaration *ad;
@@ -1937,6 +2033,55 @@ char *FuncDeclaration::kind()
{ {
return "function"; return "function";
} }
/*******************************
* Look at all the variables in this function that are referenced
* by nested functions, and determine if a closure needs to be
* created for them.
*/
#if V2
int FuncDeclaration::needsClosure()
{
/* Need a closure for all the closureVars[] if any of the
* closureVars[] are accessed by a
* function that escapes the scope of this function.
* We take the conservative approach and decide that any function that:
* 1) is a virtual function
* 2) has its address taken
* 3) has a parent that escapes
* escapes.
*/
//printf("FuncDeclaration::needsClosure() %s\n", toChars());
for (int i = 0; i < closureVars.dim; i++)
{ VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
assert(v->isVarDeclaration());
//printf("\tv = %s\n", v->toChars());
for (int j = 0; j < v->nestedrefs.dim; j++)
{ FuncDeclaration *f = (FuncDeclaration *)v->nestedrefs.data[j];
assert(f != this);
//printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
if (f->isVirtual() || f->tookAddressOf)
goto Lyes; // assume f escapes this function's scope
// Look to see if any parents of f that are below this escape
for (Dsymbol *s = f->parent; s != this; s = s->parent)
{
f = s->isFuncDeclaration();
if (f && (f->isVirtual() || f->tookAddressOf))
goto Lyes;
}
}
}
return 0;
Lyes:
//printf("\tneeds closure\n");
return 1;
}
#endif
/****************************** FuncAliasDeclaration ************************/ /****************************** FuncAliasDeclaration ************************/
@@ -2049,6 +2194,8 @@ void CtorDeclaration::semantic(Scope *sc)
Type *tret; Type *tret;
//printf("CtorDeclaration::semantic()\n"); //printf("CtorDeclaration::semantic()\n");
if (type)
return;
sc = sc->push(); sc = sc->push();
sc->stc &= ~STCstatic; // not a static constructor sc->stc &= ~STCstatic; // not a static constructor
@@ -2058,7 +2205,7 @@ void CtorDeclaration::semantic(Scope *sc)
cd = parent->isClassDeclaration(); cd = parent->isClassDeclaration();
if (!cd) if (!cd)
{ {
error("constructors only are for class definitions"); error("constructors are only for class definitions");
tret = Type::tvoid; tret = Type::tvoid;
} }
else else
@@ -2130,12 +2277,15 @@ DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
{ {
} }
DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
: FuncDeclaration(loc, endloc, id, STCundefined, NULL)
{
}
Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s) Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
{ {
DtorDeclaration *dd;
assert(!s); assert(!s);
dd = new DtorDeclaration(loc, endloc); DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
return FuncDeclaration::syntaxCopy(dd); return FuncDeclaration::syntaxCopy(dd);
} }

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -109,7 +109,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
istatex.caller = istate; istatex.caller = istate;
istatex.fd = this; istatex.fd = this;
Expressions vsave; Expressions vsave; // place to save previous parameter values
size_t dim = 0; size_t dim = 0;
if (arguments) if (arguments)
{ {
@@ -117,9 +117,40 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
assert(!dim || parameters->dim == dim); assert(!dim || parameters->dim == dim);
vsave.setDim(dim); vsave.setDim(dim);
/* Evaluate all the arguments to the function,
* store the results in eargs[]
*/
Expressions eargs;
eargs.setDim(dim);
for (size_t i = 0; i < dim; i++) for (size_t i = 0; i < dim; i++)
{ Expression *earg = (Expression *)arguments->data[i]; { Expression *earg = (Expression *)arguments->data[i];
Argument *arg = Argument::getNth(tf->parameters, i); Argument *arg = Argument::getNth(tf->parameters, i);
if (arg->storageClass & (STCout | STCref))
{
}
else
{ /* Value parameters
*/
Type *ta = arg->type->toBasetype();
if (ta->ty == Tsarray && earg->op == TOKaddress)
{
/* Static arrays are passed by a simple pointer.
* Skip past this to get at the actual arg.
*/
earg = ((AddrExp *)earg)->e1;
}
earg = earg->interpret(istate ? istate : &istatex);
if (earg == EXP_CANT_INTERPRET)
return NULL;
}
eargs.data[i] = earg;
}
for (size_t i = 0; i < dim; i++)
{ Expression *earg = (Expression *)eargs.data[i];
Argument *arg = Argument::getNth(tf->parameters, i);
VarDeclaration *v = (VarDeclaration *)parameters->data[i]; VarDeclaration *v = (VarDeclaration *)parameters->data[i];
vsave.data[i] = v->value; vsave.data[i] = v->value;
#if LOG #if LOG
@@ -161,17 +192,6 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
else else
{ /* Value parameters { /* Value parameters
*/ */
Type *ta = arg->type->toBasetype();
if (ta->ty == Tsarray && earg->op == TOKaddress)
{
/* Static arrays are passed by a simple pointer.
* Skip past this to get at the actual arg.
*/
earg = ((AddrExp *)earg)->e1;
}
earg = earg->interpret(istate ? istate : &istatex);
if (earg == EXP_CANT_INTERPRET)
return NULL;
v->value = earg; v->value = earg;
} }
#if LOG #if LOG
@@ -584,6 +604,8 @@ Expression *ForStatement::interpret(InterState *istate)
while (1) while (1)
{ {
if (!condition)
goto Lhead;
e = condition->interpret(istate); e = condition->interpret(istate);
if (e == EXP_CANT_INTERPRET) if (e == EXP_CANT_INTERPRET)
break; break;
@@ -592,7 +614,9 @@ Expression *ForStatement::interpret(InterState *istate)
break; break;
} }
if (e->isBool(TRUE)) if (e->isBool(TRUE))
{ e = body ? body->interpret(istate) : NULL; {
Lhead:
e = body ? body->interpret(istate) : NULL;
if (e == EXP_CANT_INTERPRET) if (e == EXP_CANT_INTERPRET)
break; break;
if (e == EXP_BREAK_INTERPRET) if (e == EXP_BREAK_INTERPRET)
@@ -602,9 +626,12 @@ Expression *ForStatement::interpret(InterState *istate)
if (e && e != EXP_CONTINUE_INTERPRET) if (e && e != EXP_CONTINUE_INTERPRET)
break; break;
Lcontinue: Lcontinue:
e = increment->interpret(istate); if (increment)
if (e == EXP_CANT_INTERPRET) {
break; e = increment->interpret(istate);
if (e == EXP_CANT_INTERPRET)
break;
}
} }
else if (e->isBool(FALSE)) else if (e->isBool(FALSE))
{ e = NULL; { e = NULL;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -597,8 +597,20 @@ void Lexer::scan(Token *t)
do do
{ {
p++; p++;
c = escapeSequence(); switch (*p)
stringbuffer.writeUTF8(c); {
case 'u':
case 'U':
case '&':
c = escapeSequence();
stringbuffer.writeUTF8(c);
break;
default:
c = escapeSequence();
stringbuffer.writeByte(c);
break;
}
} while (*p == '\\'); } while (*p == '\\');
t->len = stringbuffer.offset; t->len = stringbuffer.offset;
stringbuffer.writeByte(0); stringbuffer.writeByte(0);
@@ -718,6 +730,15 @@ void Lexer::scan(Token *t)
t->value = TOKint64v; t->value = TOKint64v;
t->uns64value = major * 1000 + minor; t->uns64value = major * 1000 + minor;
} }
#if V2
else if (id == Id::EOFX)
{
t->value = TOKeof;
// Advance scanner to end of file
while (!(*p == 0 || *p == 0x1A))
p++;
}
#endif
} }
//printf("t->value = %d\n",t->value); //printf("t->value = %d\n",t->value);
return; return;
@@ -1290,7 +1311,7 @@ unsigned Lexer::escapeSequence()
default: default:
if (isoctal(c)) if (isoctal(c))
{ unsigned char v; { unsigned v;
n = 0; n = 0;
v = 0; v = 0;
@@ -1300,6 +1321,8 @@ unsigned Lexer::escapeSequence()
c = *++p; c = *++p;
} while (++n < 3 && isoctal(c)); } while (++n < 3 && isoctal(c));
c = v; c = v;
if (c > 0xFF)
error("0%03o is larger than a byte", c);
} }
else else
error("undefined escape sequence \\%c\n",c); error("undefined escape sequence \\%c\n",c);
@@ -1487,7 +1510,6 @@ TOK Lexer::delimitedStringConstant(Token *t)
{ {
case '\n': case '\n':
Lnextline: Lnextline:
printf("Lnextline\n");
loc.linnum++; loc.linnum++;
startline = 1; startline = 1;
if (blankrol) if (blankrol)
@@ -1544,7 +1566,7 @@ printf("Lnextline\n");
} }
else else
{ hereid = t.ident; { hereid = t.ident;
printf("hereid = '%s'\n", hereid->toChars()); //printf("hereid = '%s'\n", hereid->toChars());
blankrol = 1; blankrol = 1;
} }
nest = 0; nest = 0;
@@ -1578,11 +1600,10 @@ printf("hereid = '%s'\n", hereid->toChars());
unsigned char *psave = p; unsigned char *psave = p;
p--; p--;
scan(&t); // read in possible heredoc identifier scan(&t); // read in possible heredoc identifier
printf("endid = '%s'\n", t.ident->toChars()); //printf("endid = '%s'\n", t.ident->toChars());
if (t.value == TOKidentifier && t.ident->equals(hereid)) if (t.value == TOKidentifier && t.ident->equals(hereid))
{ /* should check that rest of line is blank { /* should check that rest of line is blank
*/ */
printf("done\n");
goto Ldone; goto Ldone;
} }
p = psave; p = psave;
@@ -2742,13 +2763,10 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
*/ */
Identifier *Lexer::idPool(const char *s) Identifier *Lexer::idPool(const char *s)
{ unsigned len; {
Identifier *id; size_t len = strlen(s);
StringValue *sv; StringValue *sv = stringtable.update(s, len);
Identifier *id = (Identifier *) sv->ptrvalue;
len = strlen(s);
sv = stringtable.update(s, len);
id = (Identifier *) sv->ptrvalue;
if (!id) if (!id)
{ {
id = new Identifier(sv->lstring.string, TOKidentifier); id = new Identifier(sv->lstring.string, TOKidentifier);
@@ -2757,6 +2775,25 @@ Identifier *Lexer::idPool(const char *s)
return id; return id;
} }
/*********************************************
* Create a unique identifier using the prefix s.
*/
Identifier *Lexer::uniqueId(const char *s, int num)
{ char buffer[32];
size_t slen = strlen(s);
assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer));
sprintf(buffer, "%s%d", s, num);
return idPool(buffer);
}
Identifier *Lexer::uniqueId(const char *s)
{
static int num;
return uniqueId(s, ++num);
}
/**************************************** /****************************************
*/ */
@@ -2875,12 +2912,16 @@ static Keyword keywords[] =
{ "invariant", TOKinvariant }, { "invariant", TOKinvariant },
{ "unittest", TOKunittest }, { "unittest", TOKunittest },
{ "version", TOKversion }, { "version", TOKversion },
//{ "manifest", TOKmanifest },
// Added after 1.0 // Added after 1.0
{ "ref", TOKref }, { "ref", TOKref },
{ "macro", TOKmacro }, { "macro", TOKmacro },
#if V2 #if V2
{ "pure", TOKpure },
{ "nothrow", TOKnothrow },
{ "__traits", TOKtraits }, { "__traits", TOKtraits },
{ "__overloadset", TOKoverloadset },
#endif #endif
}; };
@@ -2933,6 +2974,9 @@ void Lexer::initKeywords()
Token::tochars[TOKxorass] = "^="; Token::tochars[TOKxorass] = "^=";
Token::tochars[TOKassign] = "="; Token::tochars[TOKassign] = "=";
Token::tochars[TOKconstruct] = "="; Token::tochars[TOKconstruct] = "=";
#if V2
Token::tochars[TOKblit] = "=";
#endif
Token::tochars[TOKlt] = "<"; Token::tochars[TOKlt] = "<";
Token::tochars[TOKgt] = ">"; Token::tochars[TOKgt] = ">";
Token::tochars[TOKle] = "<="; Token::tochars[TOKle] = "<=";
@@ -3016,4 +3060,5 @@ void Lexer::initKeywords()
Token::tochars[TOKtuple] = "tuple"; Token::tochars[TOKtuple] = "tuple";
Token::tochars[TOKdeclaration] = "declaration"; Token::tochars[TOKdeclaration] = "declaration";
Token::tochars[TOKdottd] = "dottd"; Token::tochars[TOKdottd] = "dottd";
Token::tochars[TOKon_scope_exit] = "scope(exit)";
} }

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -92,11 +92,11 @@ enum TOK
TOKand, TOKor, TOKxor, TOKand, TOKor, TOKxor,
TOKandass, TOKorass, TOKxorass, TOKandass, TOKorass, TOKxorass,
TOKassign, TOKnot, TOKtilde, TOKassign, TOKnot, TOKtilde,
TOKplusplus, TOKminusminus, TOKconstruct, TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
TOKdot, TOKarrow, TOKcomma, TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror, TOKquestion, TOKandand, TOKoror,
// 103 // 104
// Numeric literals // Numeric literals
TOKint32v, TOKuns32v, TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v, TOKint64v, TOKuns64v,
@@ -131,7 +131,7 @@ enum TOK
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport, TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile, TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy, TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
TOKauto, TOKpackage, TOKauto, TOKpackage, TOKmanifest,
// Statements // Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch, TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
@@ -152,6 +152,8 @@ enum TOK
TOKmacro, TOKmacro,
#if V2 #if V2
TOKtraits, TOKtraits,
TOKoverloadset,
TOKpure,
#endif #endif
TOKMAX TOKMAX
@@ -261,6 +263,8 @@ struct Lexer
static void initKeywords(); static void initKeywords();
static Identifier *idPool(const char *s); static Identifier *idPool(const char *s);
static Identifier *uniqueId(const char *s);
static Identifier *uniqueId(const char *s, int num);
TOK nextToken(); TOK nextToken();
void scan(Token *t); void scan(Token *t);

View File

@@ -296,7 +296,7 @@ int runLINK()
runtime_path.append("libtango-base-llvmdc.a"); runtime_path.append("libtango-base-llvmdc.a");
argv.push((void*)runtime_path.c_str()); argv.push((void*)runtime_path.c_str());
if (!global.params.quiet) if (!global.params.quiet || global.params.verbose)
{ {
// Print it // Print it
for (i = 0; i < argv.dim; i++) for (i = 0; i < argv.dim; i++)

View File

@@ -70,8 +70,8 @@ Global::Global()
copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen"; copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v1.029";
llvmdc_version = "0.1"; llvmdc_version = "0.1";
version = "v1.026";
global.structalign = 8; global.structalign = 8;
memset(&params, 0, sizeof(Param)); memset(&params, 0, sizeof(Param));
@@ -188,6 +188,7 @@ Usage:\n\
--help print help\n\ --help print help\n\
-I<path> where to look for imports\n\ -I<path> where to look for imports\n\
-J<path> where to look for string imports\n\ -J<path> where to look for string imports\n\
-ignore ignore unsupported pragmas\n\
-inline do function inlining\n\ -inline do function inlining\n\
-Llinkerflag pass linkerflag to link\n\ -Llinkerflag pass linkerflag to link\n\
-m<arch> emit code specific to <arch>\n\ -m<arch> emit code specific to <arch>\n\
@@ -201,9 +202,9 @@ Usage:\n\
-od<objdir> write object files to directory <objdir>\n\ -od<objdir> write object files to directory <objdir>\n\
-of<filename> name output file to <filename>\n\ -of<filename> name output file to <filename>\n\
-op do not strip paths from source file\n\ -op do not strip paths from source file\n\
-profile profile runtime performance of generated code\n\ -profile profile runtime performance of generated code\n\
-quiet suppress unnecessary messages\n\ -quiet suppress unnecessary messages\n\
-release compile release version\n\ -release compile release version\n\
-run srcfile args... run resulting program, passing args\n\ -run srcfile args... run resulting program, passing args\n\
-R<path> provide path to the directory containing the runtime library\n\ -R<path> provide path to the directory containing the runtime library\n\
-unittest compile in unit tests\n\ -unittest compile in unit tests\n\
@@ -268,6 +269,7 @@ int main(int argc, char *argv[])
global.params.llvmInline = 0; // use this one instead to know if inline passes should be run global.params.llvmInline = 0; // use this one instead to know if inline passes should be run
global.params.obj = 1; global.params.obj = 1;
global.params.Dversion = 2; global.params.Dversion = 2;
global.params.quiet = 1;
global.params.linkswitches = new Array(); global.params.linkswitches = new Array();
global.params.libfiles = new Array(); global.params.libfiles = new Array();
@@ -356,7 +358,7 @@ int main(int argc, char *argv[])
global.params.symdebug = 2; global.params.symdebug = 2;
else if (strcmp(p + 1, "gt") == 0) else if (strcmp(p + 1, "gt") == 0)
{ error("use -profile instead of -gt\n"); { error("use -profile instead of -gt\n");
global.params.trace = 1; global.params.trace = 1;
} }
else if (strcmp(p + 1, "profile") == 0) else if (strcmp(p + 1, "profile") == 0)
global.params.trace = 1; global.params.trace = 1;
@@ -476,6 +478,8 @@ int main(int argc, char *argv[])
} }
} }
#endif #endif
else if (strcmp(p + 1, "ignore") == 0)
global.params.ignoreUnsupportedPragmas = 1;
else if (strcmp(p + 1, "inline") == 0) { else if (strcmp(p + 1, "inline") == 0) {
// TODO // TODO
// the ast rewrites dmd does for inlining messes up the ast. // the ast rewrites dmd does for inlining messes up the ast.

View File

@@ -70,6 +70,7 @@ struct Param
char noruntime; // code is not allowed to make implicit calls to the runtime char noruntime; // code is not allowed to make implicit calls to the runtime
char novalidate;// no bitcode validation char novalidate;// no bitcode validation
char Dversion; // D version number char Dversion; // D version number
char ignoreUnsupportedPragmas; // rather than error on them
char *argv0; // program name char *argv0; // program name
Array *imppath; // array of char*'s of where to look for import modules Array *imppath; // array of char*'s of where to look for import modules

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars // Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -107,8 +107,13 @@ StringTable Type::stringtable;
Type::Type(TY ty, Type *next) Type::Type(TY ty, Type *next)
{ {
this->ty = ty; this->ty = ty;
this->mod = 0;
this->next = next; this->next = next;
this->deco = NULL; this->deco = NULL;
#if V2
this->cto = NULL;
this->ito = NULL;
#endif
this->pto = NULL; this->pto = NULL;
this->rto = NULL; this->rto = NULL;
this->arrayof = NULL; this->arrayof = NULL;
@@ -337,16 +342,6 @@ void Type::toDecoBuffer(OutBuffer *buf)
} }
} }
/********************************
* Name mangling.
*/
void Type::toTypeInfoBuffer(OutBuffer *buf)
{
assert(0);
buf->writeByte(mangleChar[ty]);
}
/******************************** /********************************
* For pretty-printing a type. * For pretty-printing a type.
*/ */
@@ -356,27 +351,54 @@ char *Type::toChars()
HdrGenState hgs; HdrGenState hgs;
buf = new OutBuffer(); buf = new OutBuffer();
toCBuffer2(buf, NULL, &hgs); toCBuffer(buf, NULL, &hgs);
return buf->toChars(); return buf->toChars();
} }
void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{ {
OutBuffer tbuf; toCBuffer2(buf, hgs, 0);
toCBuffer2(&tbuf, ident, hgs);
buf->write(&tbuf);
}
void Type::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{
buf->prependstring(toChars());
if (ident) if (ident)
{ buf->writeByte(' '); { buf->writeByte(' ');
buf->writestring(ident->toChars()); buf->writestring(ident->toChars());
} }
} }
void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
if (mod != this->mod)
{ toCBuffer3(buf, hgs, mod);
return;
}
buf->writestring(toChars());
}
void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
{
if (mod != this->mod)
{ char *p;
switch (this->mod)
{
case 0:
toCBuffer2(buf, hgs, this->mod);
break;
case MODconst:
p = "const(";
goto L1;
case MODinvariant:
p = "invariant(";
L1: buf->writestring(p);
toCBuffer2(buf, hgs, this->mod);
buf->writeByte(')');
break;
default:
assert(0);
}
}
}
/************************************ /************************************
*/ */
@@ -906,13 +928,14 @@ char *TypeBasic::toChars()
return dstring; return dstring;
} }
void TypeBasic::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
buf->prependstring(cstring); //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
if (ident) if (mod != this->mod)
{ buf->writeByte(' '); { toCBuffer3(buf, hgs, mod);
buf->writestring(ident->toChars()); return;
} }
buf->writestring(dstring);
} }
d_uns64 TypeBasic::size(Loc loc) d_uns64 TypeBasic::size(Loc loc)
@@ -1589,58 +1612,6 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
return e; return e;
} }
void TypeArray::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{
#if 1
OutBuffer buf2;
toPrettyBracket(&buf2, hgs);
buf->prependstring(buf2.toChars());
if (ident)
{
buf->writeByte(' ');
buf->writestring(ident->toChars());
}
next->toCBuffer2(buf, NULL, hgs);
#elif 1
// The D way
Type *t;
OutBuffer buf2;
for (t = this; 1; t = t->next)
{ TypeArray *ta;
ta = dynamic_cast<TypeArray *>(t);
if (!ta)
break;
ta->toPrettyBracket(&buf2, hgs);
}
buf->prependstring(buf2.toChars());
if (ident)
{
buf2.writestring(ident->toChars());
}
t->toCBuffer2(buf, NULL, hgs);
#else
// The C way
if (buf->offset)
{ buf->bracket('(', ')');
assert(!ident);
}
else if (ident)
buf->writestring(ident->toChars());
Type *t = this;
do
{ Expression *dim;
buf->writeByte('[');
dim = ((TypeSArray *)t)->dim;
if (dim)
buf->printf("%lld", dim->toInteger());
buf->writeByte(']');
t = t->next;
} while (t->ty == Tsarray);
t->toCBuffer2(buf, NULL, hgs);
#endif
}
/***************************** TypeSArray *****************************/ /***************************** TypeSArray *****************************/
@@ -1902,15 +1873,13 @@ void TypeSArray::toDecoBuffer(OutBuffer *buf)
next->toDecoBuffer(buf); next->toDecoBuffer(buf);
} }
void TypeSArray::toTypeInfoBuffer(OutBuffer *buf) void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
buf->writeByte(mangleChar[Tarray]);
if (next)
next->toTypeInfoBuffer(buf);
}
void TypeSArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
{ {
if (mod != this->mod)
{ toCBuffer3(buf, hgs, mod);
return;
}
next->toCBuffer2(buf, hgs, this->mod);
buf->printf("[%s]", dim->toChars()); buf->printf("[%s]", dim->toChars());
} }
@@ -2068,15 +2037,13 @@ void TypeDArray::toDecoBuffer(OutBuffer *buf)
next->toDecoBuffer(buf); next->toDecoBuffer(buf);
} }
void TypeDArray::toTypeInfoBuffer(OutBuffer *buf) void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
buf->writeByte(mangleChar[ty]);
if (next)
next->toTypeInfoBuffer(buf);
}
void TypeDArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
{ {
if (mod != this->mod)
{ toCBuffer3(buf, hgs, mod);
return;
}
next->toCBuffer2(buf, hgs, this->mod);
buf->writestring("[]"); buf->writestring("[]");
} }
@@ -2343,14 +2310,15 @@ void TypeAArray::toDecoBuffer(OutBuffer *buf)
next->toDecoBuffer(buf); next->toDecoBuffer(buf);
} }
void TypeAArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs) void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
buf->writeByte('['); if (mod != this->mod)
{ OutBuffer ibuf; { toCBuffer3(buf, hgs, mod);
return;
index->toCBuffer2(&ibuf, NULL, hgs);
buf->write(&ibuf);
} }
next->toCBuffer2(buf, hgs, this->mod);
buf->writeByte('[');
index->toCBuffer2(buf, hgs, 0);
buf->writeByte(']'); buf->writeByte(']');
} }
@@ -2415,16 +2383,16 @@ d_uns64 TypePointer::size(Loc loc)
return PTRSIZE; return PTRSIZE;
} }
void TypePointer::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
//printf("TypePointer::toCBuffer2() next = %d\n", next->ty); //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
buf->prependstring("*"); if (mod != this->mod)
if (ident) { toCBuffer3(buf, hgs, mod);
{ return;
buf->writeByte(' ');
buf->writestring(ident->toChars());
} }
next->toCBuffer2(buf, NULL, hgs); next->toCBuffer2(buf, hgs, this->mod);
if (next->ty != Tfunction)
buf->writeByte('*');
} }
MATCH TypePointer::implicitConvTo(Type *to) MATCH TypePointer::implicitConvTo(Type *to)
@@ -2509,14 +2477,14 @@ d_uns64 TypeReference::size(Loc loc)
return PTRSIZE; return PTRSIZE;
} }
void TypeReference::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
buf->prependstring("&"); if (mod != this->mod)
if (ident) { toCBuffer3(buf, hgs, mod);
{ return;
buf->writestring(ident->toChars());
} }
next->toCBuffer2(buf, NULL, hgs); next->toCBuffer2(buf, hgs, this->mod);
buf->writeByte('&');
} }
Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -2687,7 +2655,7 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf)
inuse--; inuse--;
} }
void TypeFunction::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{ {
char *p = NULL; char *p = NULL;
@@ -2696,6 +2664,8 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hg
return; return;
} }
inuse++; inuse++;
if (next && (!ident || ident->toHChars2() == ident->toChars()))
next->toCBuffer2(buf, hgs, 0);
if (hgs->ddoc != 1) if (hgs->ddoc != 1)
{ {
switch (linkage) switch (linkage)
@@ -2710,25 +2680,45 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hg
} }
} }
if (buf->offset) if (!hgs->hdrgen && p)
{ buf->writestring(p);
if (!hgs->hdrgen && p) if (ident)
buf->prependstring(p); { buf->writeByte(' ');
buf->bracket('(', ')'); buf->writestring(ident->toHChars2());
assert(!ident);
}
else
{
if (!hgs->hdrgen && p)
buf->writestring(p);
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toHChars2());
}
} }
Argument::argsToCBuffer(buf, hgs, parameters, varargs); Argument::argsToCBuffer(buf, hgs, parameters, varargs);
if (next && (!ident || ident->toHChars2() == ident->toChars())) inuse--;
next->toCBuffer2(buf, NULL, hgs); }
void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
char *p = NULL;
if (inuse)
{ inuse = 2; // flag error to caller
return;
}
inuse++;
if (next)
next->toCBuffer2(buf, hgs, 0);
if (hgs->ddoc != 1)
{
switch (linkage)
{
case LINKd: p = NULL; break;
case LINKc: p = "C "; break;
case LINKwindows: p = "Windows "; break;
case LINKpascal: p = "Pascal "; break;
case LINKcpp: p = "C++ "; break;
default:
assert(0);
}
}
if (!hgs->hdrgen && p)
buf->writestring(p);
buf->writestring(" function");
Argument::argsToCBuffer(buf, hgs, parameters, varargs);
inuse--; inuse--;
} }
@@ -2999,28 +2989,17 @@ d_uns64 TypeDelegate::size(Loc loc)
return PTRSIZE * 2; return PTRSIZE * 2;
} }
void TypeDelegate::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
#if 1 if (mod != this->mod)
OutBuffer args; { toCBuffer3(buf, hgs, mod);
return;
}
TypeFunction *tf = (TypeFunction *)next; TypeFunction *tf = (TypeFunction *)next;
Argument::argsToCBuffer(&args, hgs, tf->parameters, tf->varargs); tf->next->toCBuffer2(buf, hgs, 0);
buf->prependstring(args.toChars()); buf->writestring(" delegate");
buf->prependstring(" delegate"); Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
if (ident)
{
buf->writeByte(' ');
buf->writestring(ident->toChars());
}
next->next->toCBuffer2(buf, NULL, hgs);
#else
next->toCBuffer2(buf, Id::delegate, hgs);
if (ident)
{
buf->writestring(ident->toChars());
}
#endif
} }
Expression *TypeDelegate::defaultInit(Loc loc) Expression *TypeDelegate::defaultInit(Loc loc)
@@ -3110,7 +3089,7 @@ void TypeQualified::addIdent(Identifier *ident)
idents.push(ident); idents.push(ident);
} }
void TypeQualified::toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
{ {
int i; int i;
@@ -3340,17 +3319,14 @@ void TypeIdentifier::toDecoBuffer(OutBuffer *buf)
//buf->printf("%c%s", mangleChar[ty], name); //buf->printf("%c%s", mangleChar[ty], name);
} }
void TypeIdentifier::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
OutBuffer tmp; if (mod != this->mod)
{ toCBuffer3(buf, hgs, mod);
tmp.writestring(this->ident->toChars()); return;
toCBuffer2Helper(&tmp, NULL, hgs);
buf->prependstring(tmp.toChars());
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toChars());
} }
buf->writestring(this->ident->toChars());
toCBuffer2Helper(buf, hgs);
} }
/************************************* /*************************************
@@ -3472,17 +3448,14 @@ Type *TypeInstance::syntaxCopy()
} }
void TypeInstance::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
OutBuffer tmp; if (mod != this->mod)
{ toCBuffer3(buf, hgs, mod);
tempinst->toCBuffer(&tmp, hgs); return;
toCBuffer2Helper(&tmp, NULL, hgs);
buf->prependstring(tmp.toChars());
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toChars());
} }
tempinst->toCBuffer(buf, hgs);
toCBuffer2Helper(buf, hgs);
} }
void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
@@ -3575,19 +3548,16 @@ Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
return t->toDsymbol(sc); return t->toDsymbol(sc);
} }
void TypeTypeof::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
OutBuffer tmp; if (mod != this->mod)
{ toCBuffer3(buf, hgs, mod);
tmp.writestring("typeof("); return;
exp->toCBuffer(&tmp, hgs);
tmp.writeByte(')');
toCBuffer2Helper(&tmp, NULL, hgs);
buf->prependstring(tmp.toChars());
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toChars());
} }
buf->writestring("typeof(");
exp->toCBuffer(buf, hgs);
buf->writeByte(')');
toCBuffer2Helper(buf, hgs);
} }
Type *TypeTypeof::semantic(Loc loc, Scope *sc) Type *TypeTypeof::semantic(Loc loc, Scope *sc)
@@ -3764,18 +3734,13 @@ void TypeEnum::toDecoBuffer(OutBuffer *buf)
buf->printf("%c%s", mangleChar[ty], name); buf->printf("%c%s", mangleChar[ty], name);
} }
void TypeEnum::toTypeInfoBuffer(OutBuffer *buf) void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
toBasetype()->toTypeInfoBuffer(buf); if (mod != this->mod)
} { toCBuffer3(buf, hgs, mod);
return;
void TypeEnum::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{
buf->prependstring(sym->toChars());
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toChars());
} }
buf->writestring(sym->toChars());
} }
Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -3945,19 +3910,14 @@ void TypeTypedef::toDecoBuffer(OutBuffer *buf)
buf->printf("%c%s", mangleChar[ty], name); buf->printf("%c%s", mangleChar[ty], name);
} }
void TypeTypedef::toTypeInfoBuffer(OutBuffer *buf) void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
sym->basetype->toTypeInfoBuffer(buf);
}
void TypeTypedef::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{ {
//printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars()); //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
buf->prependstring(sym->toChars()); if (mod != this->mod)
if (ident) { toCBuffer3(buf, hgs, mod);
{ buf->writeByte(' '); return;
buf->writestring(ident->toChars());
} }
buf->writestring(sym->toChars());
} }
Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -4173,18 +4133,17 @@ void TypeStruct::toDecoBuffer(OutBuffer *buf)
buf->printf("%c%s", mangleChar[ty], name); buf->printf("%c%s", mangleChar[ty], name);
} }
void TypeStruct::toTypeInfoBuffer(OutBuffer *buf) void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
toDecoBuffer(buf); if (mod != this->mod)
} { toCBuffer3(buf, hgs, mod);
return;
}
void TypeStruct::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) TemplateInstance *ti = sym->parent->isTemplateInstance();
{ if (ti && ti->toAlias() == sym)
buf->prependbyte(' '); buf->writestring(ti->toChars());
buf->prependstring(toChars()); else
if (ident) buf->writestring(sym->toChars());
buf->writestring(ident->toChars());
} }
Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -4455,13 +4414,13 @@ void TypeClass::toDecoBuffer(OutBuffer *buf)
buf->printf("%c%s", mangleChar[ty], name); buf->printf("%c%s", mangleChar[ty], name);
} }
void TypeClass::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
buf->prependstring(sym->toChars()); if (mod != this->mod)
if (ident) { toCBuffer3(buf, hgs, mod);
{ buf->writeByte(' '); return;
buf->writestring(ident->toChars());
} }
buf->writestring(sym->toChars());
} }
Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -4928,15 +4887,9 @@ Type *TypeTuple::reliesOnTident()
return NULL; return NULL;
} }
void TypeTuple::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
OutBuffer buf2; Argument::argsToCBuffer(buf, hgs, arguments, 0);
Argument::argsToCBuffer(&buf2, hgs, arguments, 0);
buf->prependstring(buf2.toChars());
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toChars());
}
} }
void TypeTuple::toDecoBuffer(OutBuffer *buf) void TypeTuple::toDecoBuffer(OutBuffer *buf)
@@ -5084,20 +5037,16 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
} }
} }
void TypeSlice::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
OutBuffer buf2; if (mod != this->mod)
{ toCBuffer3(buf, hgs, mod);
buf2.printf("[%s .. ", lwr->toChars()); return;
buf2.printf("%s]", upr->toChars());
buf->prependstring(buf2.toChars());
if (ident)
{
buf->writeByte(' ');
buf->writestring(ident->toChars());
} }
next->toCBuffer2(buf, NULL, hgs); next->toCBuffer2(buf, hgs, this->mod);
buf->printf("[%s .. ", lwr->toChars());
buf->printf("%s]", upr->toChars());
} }
/***************************** Argument *****************************/ /***************************** Argument *****************************/
@@ -5155,7 +5104,7 @@ char *Argument::argsTypesToChars(Arguments *args, int varargs)
buf->writeByte(','); buf->writeByte(',');
arg = (Argument *)args->data[i]; arg = (Argument *)args->data[i];
argbuf.reset(); argbuf.reset();
arg->type->toCBuffer2(&argbuf, NULL, &hgs); arg->type->toCBuffer2(&argbuf, &hgs, 0);
buf->write(&argbuf); buf->write(&argbuf);
} }
if (varargs) if (varargs)
@@ -5191,7 +5140,7 @@ void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *argume
else if (arg->storageClass & STClazy) else if (arg->storageClass & STClazy)
buf->writestring("lazy "); buf->writestring("lazy ");
argbuf.reset(); argbuf.reset();
arg->type->toCBuffer2(&argbuf, arg->ident, hgs); arg->type->toCBuffer(&argbuf, arg->ident, hgs);
if (arg->defaultArg) if (arg->defaultArg)
{ {
argbuf.writestring(" = "); argbuf.writestring(" = ");

View File

@@ -105,6 +105,9 @@ extern int Tptrdiff_t;
struct Type : Object struct Type : Object
{ {
TY ty; TY ty;
unsigned char mod; // modifiers (MODconst, MODinvariant)
#define MODconst 1 // type is const
#define MODinvariant 2 // type is invariant
Type *next; Type *next;
char *deco; char *deco;
Type *pto; // merged pointer to this type Type *pto; // merged pointer to this type
@@ -193,10 +196,10 @@ struct Type : Object
virtual unsigned alignsize(); virtual unsigned alignsize();
virtual Type *semantic(Loc loc, Scope *sc); virtual Type *semantic(Loc loc, Scope *sc);
virtual void toDecoBuffer(OutBuffer *buf); virtual void toDecoBuffer(OutBuffer *buf);
virtual void toTypeInfoBuffer(OutBuffer *buf);
Type *merge(); Type *merge();
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
virtual void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
virtual int isbit(); virtual int isbit();
virtual int isintegral(); virtual int isintegral();
virtual int isfloating(); // real, imaginary, or complex virtual int isfloating(); // real, imaginary, or complex
@@ -260,7 +263,7 @@ struct TypeBasic : Type
Expression *getProperty(Loc loc, Identifier *ident); Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
char *toChars(); char *toChars();
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
int isintegral(); int isintegral();
int isbit(); int isbit();
int isfloating(); int isfloating();
@@ -281,8 +284,6 @@ struct TypeBasic : Type
struct TypeArray : Type struct TypeArray : Type
{ {
TypeArray(TY ty, Type *next); TypeArray(TY ty, Type *next);
virtual void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs) = 0;
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
}; };
@@ -298,8 +299,7 @@ struct TypeSArray : TypeArray
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString(); int isString();
int isZeroInit(); int isZeroInit();
@@ -326,8 +326,7 @@ struct TypeDArray : TypeArray
unsigned alignsize(); unsigned alignsize();
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString(); int isString();
int isZeroInit(); int isZeroInit();
@@ -351,7 +350,7 @@ struct TypeAArray : TypeArray
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -371,7 +370,7 @@ struct TypePointer : Type
Type *syntaxCopy(); Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
MATCH implicitConvTo(Type *to); MATCH implicitConvTo(Type *to);
int isscalar(); int isscalar();
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
@@ -387,7 +386,7 @@ struct TypeReference : Type
TypeReference(Type *t); TypeReference(Type *t);
Type *syntaxCopy(); Type *syntaxCopy();
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
int isZeroInit(); int isZeroInit();
@@ -412,7 +411,8 @@ struct TypeFunction : Type
Type *syntaxCopy(); Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration(); TypeInfoDeclaration *getTypeInfoDeclaration();
Type *reliesOnTident(); Type *reliesOnTident();
@@ -433,7 +433,7 @@ struct TypeDelegate : Type
Type *syntaxCopy(); Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
int isZeroInit(); int isZeroInit();
int checkBoolean(); int checkBoolean();
@@ -452,7 +452,7 @@ struct TypeQualified : Type
TypeQualified(TY ty, Loc loc); TypeQualified(TY ty, Loc loc);
void syntaxCopyHelper(TypeQualified *t); void syntaxCopyHelper(TypeQualified *t);
void addIdent(Identifier *ident); void addIdent(Identifier *ident);
void toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym, void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
Expression **pe, Type **pt, Dsymbol **ps); Expression **pe, Type **pt, Dsymbol **ps);
@@ -466,7 +466,7 @@ struct TypeIdentifier : TypeQualified
Type *syntaxCopy(); Type *syntaxCopy();
//char *toChars(); //char *toChars();
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Dsymbol *toDsymbol(Scope *sc); Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
@@ -485,7 +485,7 @@ struct TypeInstance : TypeQualified
Type *syntaxCopy(); Type *syntaxCopy();
//char *toChars(); //char *toChars();
//void toDecoBuffer(OutBuffer *buf); //void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -498,7 +498,7 @@ struct TypeTypeof : TypeQualified
TypeTypeof(Loc loc, Expression *exp); TypeTypeof(Loc loc, Expression *exp);
Type *syntaxCopy(); Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc); Dsymbol *toDsymbol(Scope *sc);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
}; };
@@ -515,8 +515,7 @@ struct TypeStruct : Type
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc); Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
unsigned memalign(unsigned salign); unsigned memalign(unsigned salign);
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
@@ -541,8 +540,7 @@ struct TypeEnum : Type
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc); Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident); Expression *getProperty(Loc loc, Identifier *ident);
int isintegral(); int isintegral();
@@ -572,8 +570,7 @@ struct TypeTypedef : Type
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc); Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toTypeInfoBuffer(OutBuffer *buf); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident); Expression *getProperty(Loc loc, Identifier *ident);
int isbit(); int isbit();
@@ -609,7 +606,7 @@ struct TypeClass : Type
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc); Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
ClassDeclaration *isClassHandle(); ClassDeclaration *isClassHandle();
int isBaseOf(Type *t, int *poffset); int isBaseOf(Type *t, int *poffset);
@@ -637,7 +634,7 @@ struct TypeTuple : Type
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
int equals(Object *o); int equals(Object *o);
Type *reliesOnTident(); Type *reliesOnTident();
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toDecoBuffer(OutBuffer *buf); void toDecoBuffer(OutBuffer *buf);
Expression *getProperty(Loc loc, Identifier *ident); Expression *getProperty(Loc loc, Identifier *ident);
TypeInfoDeclaration *getTypeInfoDeclaration(); TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -652,7 +649,7 @@ struct TypeSlice : Type
Type *syntaxCopy(); Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
}; };
/**************************************************************/ /**************************************************************/

View File

@@ -637,6 +637,14 @@ Condition *Parser::parseVersionCondition()
id = token.ident; id = token.ident;
else if (token.value == TOKint32v) else if (token.value == TOKint32v)
level = (unsigned)token.uns64value; level = (unsigned)token.uns64value;
#if V2
/* Allow:
* version (unittest)
* even though unittest is a keyword
*/
else if (token.value == TOKunittest)
id = Lexer::idPool(Token::toChars(TOKunittest));
#endif
else else
error("identifier or integer expected, not %s", token.toChars()); error("identifier or integer expected, not %s", token.toChars());
nextToken(); nextToken();

View File

@@ -69,6 +69,7 @@ Scope::Scope()
this->incontract = 0; this->incontract = 0;
this->nofree = 0; this->nofree = 0;
this->noctor = 0; this->noctor = 0;
this->noaccesscheck = 0;
this->intypeof = 0; this->intypeof = 0;
this->parameterSpecialization = 0; this->parameterSpecialization = 0;
this->callSuper = 0; this->callSuper = 0;
@@ -115,6 +116,7 @@ Scope::Scope(Scope *enclosing)
this->incontract = enclosing->incontract; this->incontract = enclosing->incontract;
this->nofree = 0; this->nofree = 0;
this->noctor = enclosing->noctor; this->noctor = enclosing->noctor;
this->noaccesscheck = enclosing->noaccesscheck;
this->intypeof = enclosing->intypeof; this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization; this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper; this->callSuper = enclosing->callSuper;

View File

@@ -56,6 +56,7 @@ struct Scope
int noctor; // set if constructor calls aren't allowed int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp) int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
unsigned callSuper; // primitive flow analysis for constructors unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this() #define CSXthis_ctor 1 // called this()

View File

@@ -522,7 +522,7 @@ int CompoundStatement::usesEH()
int CompoundStatement::fallOffEnd() int CompoundStatement::fallOffEnd()
{ int falloff = TRUE; { int falloff = TRUE;
//printf("CompoundStatement::fallOffEnd()\n"); //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
for (int i = 0; i < statements->dim; i++) for (int i = 0; i < statements->dim; i++)
{ Statement *s = (Statement *)statements->data[i]; { Statement *s = (Statement *)statements->data[i];
@@ -3251,7 +3251,7 @@ int TryFinallyStatement::usesEH()
int TryFinallyStatement::fallOffEnd() int TryFinallyStatement::fallOffEnd()
{ int result; { int result;
result = body->fallOffEnd(); result = body ? body->fallOffEnd() : TRUE;
// if (finalbody) // if (finalbody)
// result = finalbody->fallOffEnd(); // result = finalbody->fallOffEnd();
return result; return result;

View File

@@ -130,6 +130,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
Dsymbol *s2 = isDsymbol(o2); Dsymbol *s2 = isDsymbol(o2);
Tuple *v1 = isTuple(o1); Tuple *v1 = isTuple(o1);
Tuple *v2 = isTuple(o2); Tuple *v2 = isTuple(o2);
//printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
/* A proper implementation of the various equals() overrides /* A proper implementation of the various equals() overrides
* should make it possible to just do o1->equals(o2), but * should make it possible to just do o1->equals(o2), but
@@ -158,7 +159,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
} }
if (!t2 || !t1->equals(t2)) if (!t2 || !t1->equals(t2))
goto L1; goto Lnomatch;
} }
else if (e1) else if (e1)
{ {
@@ -168,33 +169,39 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
printf("match %d\n", e1->equals(e2)); printf("match %d\n", e1->equals(e2));
e1->print(); e1->print();
e2->print(); e2->print();
e1->type->print();
e2->type->print();
} }
#endif #endif
if (!e2 || !e1->equals(e2)) if (!e2)
goto L1; goto Lnomatch;
if (!e1->equals(e2))
goto Lnomatch;
} }
else if (s1) else if (s1)
{ {
//printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars()); //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
goto L1; {
goto Lnomatch;
}
} }
else if (v1) else if (v1)
{ {
if (!v2) if (!v2)
goto L1; goto Lnomatch;
if (v1->objects.dim != v2->objects.dim) if (v1->objects.dim != v2->objects.dim)
goto L1; goto Lnomatch;
for (size_t i = 0; i < v1->objects.dim; i++) for (size_t i = 0; i < v1->objects.dim; i++)
{ {
if (!match((Object *)v1->objects.data[i], if (!match((Object *)v1->objects.data[i],
(Object *)v2->objects.data[i], (Object *)v2->objects.data[i],
tempdecl, sc)) tempdecl, sc))
goto L1; goto Lnomatch;
} }
} }
return 1; // match return 1; // match
L1: Lnomatch:
return 0; // nomatch; return 0; // nomatch;
} }
@@ -268,6 +275,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, TemplateParame
#endif #endif
this->loc = loc; this->loc = loc;
this->parameters = parameters; this->parameters = parameters;
this->origParameters = parameters;
this->members = decldefs; this->members = decldefs;
this->overnext = NULL; this->overnext = NULL;
this->overroot = NULL; this->overroot = NULL;
@@ -336,6 +344,17 @@ void TemplateDeclaration::semantic(Scope *sc)
Scope *paramscope = sc->push(paramsym); Scope *paramscope = sc->push(paramsym);
paramscope->parameterSpecialization = 1; paramscope->parameterSpecialization = 1;
if (global.params.doDocComments)
{
origParameters = new TemplateParameters();
origParameters->setDim(parameters->dim);
for (int i = 0; i < parameters->dim; i++)
{
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
origParameters->data[i] = (void *)tp->syntaxCopy();
}
}
for (int i = 0; i < parameters->dim; i++) for (int i = 0; i < parameters->dim; i++)
{ {
TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
@@ -348,6 +367,8 @@ void TemplateDeclaration::semantic(Scope *sc)
TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
tp->semantic(paramscope); tp->semantic(paramscope);
if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
error("template tuple parameter must be last one");
} }
paramscope->pop(); paramscope->pop();
@@ -437,6 +458,7 @@ int TemplateDeclaration::overloadInsert(Dsymbol *s)
* those deduced types in dedtypes[]. * those deduced types in dedtypes[].
* Input: * Input:
* flag 1: don't do semantic() because of dummy types * flag 1: don't do semantic() because of dummy types
* 2: don't change types in matchArg()
* Output: * Output:
* dedtypes deduced arguments * dedtypes deduced arguments
* Return match level. * Return match level.
@@ -447,8 +469,9 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
{ MATCH m; { MATCH m;
int dedtypes_dim = dedtypes->dim; int dedtypes_dim = dedtypes->dim;
#if LOG #define LOGM 0
printf("+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag); #if LOGM
printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
#endif #endif
#if 0 #if 0
@@ -466,7 +489,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
// If more arguments than parameters, no match // If more arguments than parameters, no match
if (ti->tiargs->dim > parameters_dim && !variadic) if (ti->tiargs->dim > parameters_dim && !variadic)
{ {
#if LOG #if LOGM
printf(" no match: more arguments than parameters\n"); printf(" no match: more arguments than parameters\n");
#endif #endif
return MATCHnomatch; return MATCHnomatch;
@@ -489,7 +512,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
Declaration *sparam; Declaration *sparam;
//printf("\targument [%d]\n", i); //printf("\targument [%d]\n", i);
#if 0 #if LOGM
//printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null"); //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
if (ttp) if (ttp)
@@ -528,7 +551,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
} }
} }
#if 0 #if LOGM
// Print out the results // Print out the results
printf("--------------------------\n"); printf("--------------------------\n");
printf("template %s\n", toChars()); printf("template %s\n", toChars());
@@ -553,20 +576,20 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
goto Lnomatch; goto Lnomatch;
#endif #endif
#if LOG #if LOGM
printf(" match = %d\n", m); printf(" match = %d\n", m);
#endif #endif
goto Lret; goto Lret;
Lnomatch: Lnomatch:
#if LOG #if LOGM
printf(" no match\n"); printf(" no match\n");
#endif #endif
m = MATCHnomatch; m = MATCHnomatch;
Lret: Lret:
paramscope->pop(); paramscope->pop();
#if LOG #if LOGM
printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m); printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
#endif #endif
return m; return m;
@@ -645,6 +668,8 @@ int TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
* fargs arguments to function * fargs arguments to function
* Output: * Output:
* dedargs Expression/Type deduced template arguments * dedargs Expression/Type deduced template arguments
* Returns:
* match level
*/ */
MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs, MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs,
@@ -652,12 +677,13 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressi
{ {
size_t i; size_t i;
size_t nfparams; size_t nfparams;
size_t nfparams2;
size_t nfargs; size_t nfargs;
size_t nargsi; size_t nargsi; // array size of targsi
int fptupindex = -1;
int tuple_dim = 0;
MATCH match = MATCHexact; MATCH match = MATCHexact;
FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
TypeFunction *fdtype; TypeFunction *fdtype; // type of fd
TemplateTupleParameter *tp; TemplateTupleParameter *tp;
Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
@@ -682,13 +708,19 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressi
paramsym->parent = scope->parent; paramsym->parent = scope->parent;
Scope *paramscope = scope->push(paramsym); Scope *paramscope = scope->push(paramsym);
tp = isVariadic();
nargsi = 0; nargsi = 0;
if (targsi) if (targsi)
{ // Set initial template arguments { // Set initial template arguments
nargsi = targsi->dim; nargsi = targsi->dim;
if (nargsi > parameters->dim) if (nargsi > parameters->dim)
goto Lnomatch; { if (!tp)
goto Lnomatch;
dedargs->setDim(nargsi);
dedargs->zero();
}
memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data)); memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
@@ -698,6 +730,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressi
Declaration *sparam; Declaration *sparam;
m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam); m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
//printf("\tdeduceType m = %d\n", m);
if (m == MATCHnomatch) if (m == MATCHnomatch)
goto Lnomatch; goto Lnomatch;
if (m < match) if (m < match)
@@ -713,7 +746,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressi
fdtype = (TypeFunction *)fd->type; fdtype = (TypeFunction *)fd->type;
nfparams = Argument::dim(fdtype->parameters); // number of function parameters nfparams = Argument::dim(fdtype->parameters); // number of function parameters
nfparams2 = nfparams;
nfargs = fargs->dim; // number of function arguments nfargs = fargs->dim; // number of function arguments
/* Check for match of function arguments with variadic template /* Check for match of function arguments with variadic template
@@ -723,7 +755,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressi
* void main() { Foo(1,2,3); } * void main() { Foo(1,2,3); }
*/ */
tp = isVariadic(); tp = isVariadic();
if (tp) if (tp) // if variadic
{ {
if (nfparams == 0) // if no function parameters if (nfparams == 0) // if no function parameters
{ {
@@ -736,33 +768,38 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressi
goto L1; goto L1;
else else
{ {
/* See if 'A' of the template parameter matches 'A' /* Figure out which of the function parameters matches
* of the type of the last function parameter. * the tuple template parameter. Do this by matching
* type identifiers.
* Set the index of this function parameter to fptupindex.
*/ */
Argument *fparam = (Argument *)fdtype->parameters->data[nfparams - 1]; for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
if (fparam->type->ty != Tident) {
goto L1; Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex];
TypeIdentifier *tid = (TypeIdentifier *)fparam->type; if (fparam->type->ty != Tident)
if (!tp->ident->equals(tid->ident) || tid->idents.dim) continue;
goto L1; TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
if (!tp->ident->equals(tid->ident) || tid->idents.dim)
continue;
if (fdtype->varargs) // variadic function doesn't if (fdtype->varargs) // variadic function doesn't
goto Lnomatch; // go with variadic template goto Lnomatch; // go with variadic template
/* The types of the function arguments [nfparams - 1 .. nfargs] /* The types of the function arguments
* now form the tuple argument. * now form the tuple argument.
*/ */
Tuple *t = new Tuple(); Tuple *t = new Tuple();
dedargs->data[parameters->dim - 1] = (void *)t; dedargs->data[parameters->dim - 1] = (void *)t;
int tuple_dim = nfargs - (nfparams - 1); tuple_dim = nfargs - (nfparams - 1);
t->objects.setDim(tuple_dim); t->objects.setDim(tuple_dim);
for (i = 0; i < tuple_dim; i++) for (i = 0; i < tuple_dim; i++)
{ Expression *farg = (Expression *)fargs->data[nfparams - 1 + i]; { Expression *farg = (Expression *)fargs->data[fptupindex + i];
t->objects.data[i] = (void *)farg->type; t->objects.data[i] = (void *)farg->type;
}
goto L2;
} }
nfparams2--; // don't consider the last parameter for type deduction fptupindex = -1;
goto L2;
} }
} }
@@ -778,11 +815,19 @@ L1:
L2: L2:
// Loop through the function parameters // Loop through the function parameters
for (i = 0; i < nfparams2; i++) for (i = 0; i < nfparams; i++)
{ {
/* Skip over function parameters which wound up
* as part of a template tuple parameter.
*/
if (i == fptupindex)
{ if (fptupindex == nfparams - 1)
break;
i += tuple_dim - 1;
continue;
}
Argument *fparam = Argument::getNth(fdtype->parameters, i); Argument *fparam = Argument::getNth(fdtype->parameters, i);
Expression *farg;
MATCH m;
if (i >= nfargs) // if not enough arguments if (i >= nfargs) // if not enough arguments
{ {
@@ -794,12 +839,13 @@ L2:
} }
} }
else else
{ farg = (Expression *)fargs->data[i]; { Expression *farg = (Expression *)fargs->data[i];
#if 0 #if 0
printf("\tfarg->type = %s\n", farg->type->toChars()); printf("\tfarg->type = %s\n", farg->type->toChars());
printf("\tfparam->type = %s\n", fparam->type->toChars()); printf("\tfparam->type = %s\n", fparam->type->toChars());
#endif #endif
MATCH m;
m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes); m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes);
//printf("\tdeduceType m = %d\n", m); //printf("\tdeduceType m = %d\n", m);
@@ -852,30 +898,40 @@ Lmatch:
for (i = nargsi; i < dedargs->dim; i++) for (i = nargsi; i < dedargs->dim; i++)
{ {
TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
//printf("tp[%d] = %s\n", i, tp->ident->toChars());
/* For T:T*, the dedargs is the T*, dedtypes is the T
* But for function templates, we really need them to match
*/
Object *oarg = (Object *)dedargs->data[i]; Object *oarg = (Object *)dedargs->data[i];
Object *o = (Object *)dedtypes.data[i]; Object *oded = (Object *)dedtypes.data[i];
//printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, o); //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
if (!oarg) if (!oarg)
{ {
if (o) if (oded)
{ {
if (tp->specialization()) if (tp->specialization())
error("specialization not allowed for deduced parameter %s", tp->ident->toChars()); { /* The specialization can work as long as afterwards
* the oded == oarg
*/
Declaration *sparam;
dedargs->data[i] = (void *)oded;
MATCH m2 = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
//printf("m2 = %d\n", m2);
if (!m2)
goto Lnomatch;
if (m2 < match)
match = m2; // pick worst match
if (dedtypes.data[i] != oded)
error("specialization not allowed for deduced parameter %s", tp->ident->toChars());
}
} }
else else
{ o = tp->defaultArg(paramscope); { oded = tp->defaultArg(paramscope);
if (!o) if (!oded)
goto Lnomatch; goto Lnomatch;
#if 0
Match m;
Declaration *sparam;
m = tp->matchArg(paramscope, dedargs, i, parameters, &sparam);
if (!m)
goto Lnomatch;
#endif
} }
declareParameter(paramscope, tp, o); declareParameter(paramscope, tp, oded);
dedargs->data[i] = (void *)o; dedargs->data[i] = (void *)oded;
} }
} }
@@ -887,7 +943,7 @@ Lmatch:
#endif #endif
paramscope->pop(); paramscope->pop();
//printf("\tmatch\n"); //printf("\tmatch %d\n", match);
return match; return match;
Lnomatch: Lnomatch:
@@ -1044,9 +1100,9 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
int c2 = td_best->leastAsSpecialized(td); int c2 = td_best->leastAsSpecialized(td);
//printf("c1 = %d, c2 = %d\n", c1, c2); //printf("c1 = %d, c2 = %d\n", c1, c2);
if (c1 && !c2) if (c1 > c2)
goto Ltd; goto Ltd;
else if (!c1 && c2) else if (c1 < c2)
goto Ltd_best; goto Ltd_best;
else else
goto Lambig; goto Lambig;
@@ -1116,6 +1172,8 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
for (int i = 0; i < parameters->dim; i++) for (int i = 0; i < parameters->dim; i++)
{ {
TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
if (hgs->ddoc)
tp = (TemplateParameter *)origParameters->data[i];
if (i) if (i)
buf->writeByte(','); buf->writeByte(',');
tp->toCBuffer(buf, hgs); tp->toCBuffer(buf, hgs);
@@ -1516,7 +1574,19 @@ MATCH TypeInstance::deduceType(Scope *sc,
*/ */
int i = templateIdentifierLookup(tp->tempinst->name, parameters); int i = templateIdentifierLookup(tp->tempinst->name, parameters);
if (i == -1) if (i == -1)
{ /* Didn't find it as a parameter identifier. Try looking
* it up and seeing if is an alias. See Bugzilla 1454
*/
Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
if (s)
{
s = s->toAlias();
TemplateDeclaration *td = s->isTemplateDeclaration();
if (td && td == tempinst->tempdecl)
goto L2;
}
goto Lnomatch; goto Lnomatch;
}
TemplateParameter *tpx = (TemplateParameter *)parameters->data[i]; TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
// This logic duplicates tpx->matchArg() // This logic duplicates tpx->matchArg()
TemplateAliasParameter *ta = tpx->isTemplateAliasParameter(); TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
@@ -1540,12 +1610,14 @@ MATCH TypeInstance::deduceType(Scope *sc,
else if (tempinst->tempdecl != tp->tempinst->tempdecl) else if (tempinst->tempdecl != tp->tempinst->tempdecl)
goto Lnomatch; goto Lnomatch;
L2:
if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim) if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim)
goto Lnomatch; goto Lnomatch;
for (int i = 0; i < tempinst->tiargs->dim; i++) for (int i = 0; i < tempinst->tiargs->dim; i++)
{ {
//printf("test: [%d]\n", i); //printf("\ttest: tempinst->tiargs[%d]\n", i);
int j;
Object *o1 = (Object *)tempinst->tiargs->data[i]; Object *o1 = (Object *)tempinst->tiargs->data[i];
Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
@@ -1570,18 +1642,29 @@ MATCH TypeInstance::deduceType(Scope *sc,
else if (e1 && e2) else if (e1 && e2)
{ {
if (!e1->equals(e2)) if (!e1->equals(e2))
{ if (e2->op == TOKvar)
{
/*
* (T:Number!(e2), int e2)
*/
j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
goto L1;
}
goto Lnomatch; goto Lnomatch;
}
} }
else if (e1 && t2 && t2->ty == Tident) else if (e1 && t2 && t2->ty == Tident)
{ int i = templateParameterLookup(t2, parameters); {
if (i == -1) j = templateParameterLookup(t2, parameters);
L1:
if (j == -1)
goto Lnomatch; goto Lnomatch;
TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
// BUG: use tp->matchArg() instead of the following // BUG: use tp->matchArg() instead of the following
TemplateValueParameter *tv = tp->isTemplateValueParameter(); TemplateValueParameter *tv = tp->isTemplateValueParameter();
if (!tv) if (!tv)
goto Lnomatch; goto Lnomatch;
Expression *e = (Expression *)dedtypes->data[i]; Expression *e = (Expression *)dedtypes->data[j];
if (e) if (e)
{ {
if (!e1->equals(e)) if (!e1->equals(e))
@@ -1592,7 +1675,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
MATCH m = (MATCH)e1->implicitConvTo(vt); MATCH m = (MATCH)e1->implicitConvTo(vt);
if (!m) if (!m)
goto Lnomatch; goto Lnomatch;
dedtypes->data[i] = e1; dedtypes->data[j] = e1;
} }
} }
// BUG: Need to handle alias and tuple parameters // BUG: Need to handle alias and tuple parameters
@@ -2351,6 +2434,7 @@ Lmatch:
return m; return m;
Lnomatch: Lnomatch:
//printf("\tno match\n");
*psparam = NULL; *psparam = NULL;
return MATCHnomatch; return MATCHnomatch;
} }
@@ -2780,7 +2864,7 @@ void TemplateInstance::semantic(Scope *sc)
if (m->semanticdone >= 3) if (m->semanticdone >= 3)
dosemantic3 = 1; dosemantic3 = 1;
} }
for (i = 0; 1; i++) for (int i = 0; 1; i++)
{ {
if (i == a->dim) if (i == a->dim)
{ {
@@ -2953,7 +3037,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs)
Expression *ea = isExpression(o); Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o); Dsymbol *sa = isDsymbol(o);
//printf("1: tiargs->data[%d] = %p, %p, %p\n", j, o, isDsymbol(o), isTuple(o)); //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
if (ta) if (ta)
{ {
//printf("type %s\n", ta->toChars()); //printf("type %s\n", ta->toChars());
@@ -3196,9 +3280,9 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
int c2 = td_best->leastAsSpecialized(td); int c2 = td_best->leastAsSpecialized(td);
//printf("c1 = %d, c2 = %d\n", c1, c2); //printf("c1 = %d, c2 = %d\n", c1, c2);
if (c1 && !c2) if (c1 > c2)
goto Ltd; goto Ltd;
else if (!c1 && c2) else if (c1 < c2)
goto Ltd_best; goto Ltd_best;
else else
goto Lambig; goto Lambig;
@@ -3305,10 +3389,30 @@ int TemplateInstance::isNested(Objects *args)
{ {
// if module level template // if module level template
if (tempdecl->toParent()->isModule()) if (tempdecl->toParent()->isModule())
{ { Dsymbol *dparent = d->toParent();
if (isnested && isnested != d->toParent()) if (!isnested)
error("inconsistent nesting levels %s and %s", isnested->toChars(), d->toParent()->toChars()); isnested = dparent;
isnested = d->toParent(); else if (isnested != dparent)
{
/* Select the more deeply nested of the two.
* Error if one is not nested inside the other.
*/
for (Dsymbol *p = isnested; p; p = p->parent)
{
if (p == dparent)
goto L1; // isnested is most nested
}
for (Dsymbol *p = dparent; 1; p = p->parent)
{
if (p == isnested)
{ isnested = dparent;
goto L1; // dparent is most nested
}
}
error("is nested in both %s and %s", isnested->toChars(), dparent->toChars());
}
L1:
//printf("\tnested inside %s\n", isnested->toChars());
nested |= 1; nested |= 1;
} }
else else

View File

@@ -49,6 +49,9 @@ struct Tuple : Object
struct TemplateDeclaration : ScopeDsymbol struct TemplateDeclaration : ScopeDsymbol
{ {
TemplateParameters *parameters; // array of TemplateParameter's TemplateParameters *parameters; // array of TemplateParameter's
TemplateParameters *origParameters; // originals for Ddoc
Array instances; // array of TemplateInstance's Array instances; // array of TemplateInstance's
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration TemplateDeclaration *overnext; // next overloaded TemplateDeclaration