Merge DMD 1.051

This commit is contained in:
Christian Kamm
2009-11-06 23:58:01 +01:00
parent 64a8e47ad6
commit 3479e91996
46 changed files with 19557 additions and 16589 deletions

View File

@@ -62,13 +62,19 @@ struct AggregateDeclaration : ScopeDsymbol
// 1: size is correct
// 2: cannot determine size; fwd referenced
int isdeprecated; // !=0 if deprecated
Scope *scope; // !=NULL means context to use
// Special member functions
InvariantDeclaration *inv; // invariant
NewDeclaration *aggNew; // allocator
DeleteDeclaration *aggDelete; // deallocator
#if DMDV2
//CtorDeclaration *ctor;
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
CtorDeclaration *defaultCtor; // default constructor
Dsymbol *aliasthis; // forward unresolved lookups to aliasthis
#endif
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *dtor; // aggregate destructor
@@ -88,6 +94,7 @@ struct AggregateDeclaration : ScopeDsymbol
FuncDeclaration *buildDtor(Scope *sc);
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
// For access checking

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -31,6 +31,14 @@
Expression *BinExp::arrayOp(Scope *sc)
{
//printf("BinExp::arrayOp() %s\n", toChars());
if (type->toBasetype()->nextOf()->toBasetype()->ty == Tvoid)
{
error("Cannot perform array operations on void[] arrays");
return new ErrorExp();
}
Expressions *arguments = new Expressions();
/* The expression to generate an array operation for is mangled
@@ -288,6 +296,8 @@ Expression *BinExp::arrayOp(Scope *sc)
sc->stc = 0;
sc->linkage = LINKd;
fd->semantic(sc);
fd->semantic2(sc);
fd->semantic3(sc);
sc->pop();
// }
// else
@@ -318,6 +328,17 @@ void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
arguments->shift(this);
}
void CastExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
Type *tb = type->toBasetype();
if (tb->ty == Tarray || tb->ty == Tsarray)
{
e1->buildArrayIdent(buf, arguments);
}
else
Expression::buildArrayIdent(buf, arguments);
}
void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
{
buf->writestring("Slice");
@@ -402,6 +423,17 @@ Expression *Expression::buildArrayLoop(Arguments *fparams)
return e;
}
Expression *CastExp::buildArrayLoop(Arguments *fparams)
{
Type *tb = type->toBasetype();
if (tb->ty == Tarray || tb->ty == Tsarray)
{
return e1->buildArrayLoop(fparams);
}
else
return Expression::buildArrayLoop(fparams);
}
Expression *SliceExp::buildArrayLoop(Arguments *fparams)
{
Identifier *id = Identifier::generateId("p", fparams->dim);
@@ -420,6 +452,14 @@ Expression *AssignExp::buildArrayLoop(Arguments *fparams)
/* Evaluate assign expressions right to left
*/
Expression *ex2 = e2->buildArrayLoop(fparams);
#if DMDV2
/* Need the cast because:
* b = c + p[i];
* where b is a byte fails because (c + p[i]) is an int
* which cannot be implicitly cast to byte.
*/
ex2 = new CastExp(0, ex2, e1->type->nextOf());
#endif
Expression *ex1 = e1->buildArrayLoop(fparams);
Argument *param = (Argument *)fparams->data[0];
param->storageClass = 0;
@@ -488,3 +528,34 @@ X(Or)
#undef X
/***********************************************
* Test if operand is a valid array op operand.
*/
int Expression::isArrayOperand()
{
//printf("Expression::isArrayOperand() %s\n", toChars());
if (op == TOKslice)
return 1;
if (type->toBasetype()->ty == Tarray)
{
switch (op)
{
case TOKadd:
case TOKmin:
case TOKmul:
case TOKdiv:
case TOKmod:
case TOKxor:
case TOKand:
case TOKor:
case TOKneg:
case TOKtilde:
return 1;
default:
break;
}
}
return 0;
}

View File

@@ -26,6 +26,9 @@
#include "module.h"
#include "parse.h"
#include "template.h"
#if TARGET_NET
#include "frontend.net/pragma.h"
#endif
#if IN_LLVM
#include "../gen/enums.h"
@@ -74,6 +77,76 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
return m;
}
void AttribDeclaration::setScopeNewSc(Scope *sc,
unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection,
unsigned structalign)
{
if (decl)
{
Scope *newsc = sc;
if (stc != sc->stc ||
linkage != sc->linkage ||
protection != sc->protection ||
explicitProtection != sc->explicitProtection ||
structalign != sc->structalign)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;
newsc->stc = stc;
newsc->linkage = linkage;
newsc->protection = protection;
newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign;
}
for (unsigned i = 0; i < decl->dim; i++)
{ Dsymbol *s = (Dsymbol *)decl->data[i];
s->setScope(newsc); // yes, the only difference from semanticNewSc()
}
if (newsc != sc)
{
sc->offset = newsc->offset;
newsc->pop();
}
}
}
void AttribDeclaration::semanticNewSc(Scope *sc,
unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection,
unsigned structalign)
{
if (decl)
{
Scope *newsc = sc;
if (stc != sc->stc ||
linkage != sc->linkage ||
protection != sc->protection ||
explicitProtection != sc->explicitProtection ||
structalign != sc->structalign)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;
newsc->stc = stc;
newsc->linkage = linkage;
newsc->protection = protection;
newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign;
}
for (unsigned i = 0; i < decl->dim; i++)
{ Dsymbol *s = (Dsymbol *)decl->data[i];
s->semantic(newsc);
}
if (newsc != sc)
{
sc->offset = newsc->offset;
newsc->pop();
}
}
}
void AttribDeclaration::semantic(Scope *sc)
{
Array *d = include(sc, NULL);
@@ -302,24 +375,50 @@ Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
return scd;
}
void StorageClassDeclaration::setScope(Scope *sc)
{
if (decl)
{
unsigned scstc = sc->stc;
/* These sets of storage classes are mutually exclusive,
* so choose the innermost or most recent one.
*/
if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
if (stc & (STCconst | STCimmutable | STCmanifest))
scstc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls))
scstc &= ~(STCgshared | STCshared | STCtls);
scstc |= stc;
setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
}
}
void StorageClassDeclaration::semantic(Scope *sc)
{
if (decl)
{ unsigned stc_save = sc->stc;
{
unsigned scstc = sc->stc;
if (stc & (STCauto | STCscope | STCstatic | STCextern))
sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
sc->stc |= stc;
for (unsigned i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
/* These sets of storage classes are mutually exclusive,
* so choose the innermost or most recent one.
*/
if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
if (stc & (STCconst | STCimmutable | STCmanifest))
scstc &= ~(STCconst | STCimmutable | STCmanifest);
if (stc & (STCgshared | STCshared | STCtls))
scstc &= ~(STCgshared | STCshared | STCtls);
scstc |= stc;
s->semantic(sc);
}
sc->stc = stc_save;
semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
}
else
sc->stc = stc;
}
void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
@@ -337,17 +436,11 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
{ STCstatic, TOKstatic },
{ STCextern, TOKextern },
{ STCconst, TOKconst },
// { STCinvariant, TOKimmutable },
// { STCshared, TOKshared },
{ STCfinal, TOKfinal },
{ STCabstract, TOKabstract },
{ STCsynchronized, TOKsynchronized },
{ STCdeprecated, TOKdeprecated },
{ STCoverride, TOKoverride },
// { STCnothrow, TOKnothrow },
// { STCpure, TOKpure },
// { STCref, TOKref },
// { STCtls, TOKtls },
};
for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
@@ -384,24 +477,21 @@ Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
return ld;
}
void LinkDeclaration::setScope(Scope *sc)
{
//printf("LinkDeclaration::setScope(linkage = %d, decl = %p)\n", linkage, decl);
if (decl)
{
setScopeNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
}
}
void LinkDeclaration::semantic(Scope *sc)
{
//printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
if (decl)
{ enum LINK linkage_save = sc->linkage;
sc->linkage = linkage;
for (unsigned i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
s->semantic(sc);
}
sc->linkage = linkage_save;
}
else
{
sc->linkage = linkage;
semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
}
}
@@ -473,31 +563,48 @@ Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
return pd;
}
void ProtDeclaration::semantic(Scope *sc)
void ProtDeclaration::setScope(Scope *sc)
{
if (decl)
{ enum PROT protection_save = sc->protection;
int explicitProtection_save = sc->explicitProtection;
sc->protection = protection;
sc->explicitProtection = 1;
for (unsigned i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
s->semantic(sc);
}
sc->protection = protection_save;
sc->explicitProtection = explicitProtection_save;
}
else
{ sc->protection = protection;
sc->explicitProtection = 1;
{
setScopeNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
}
}
void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ const char *p;
void ProtDeclaration::importAll(Scope *sc)
{
Scope *newsc = sc;
if (sc->protection != protection ||
sc->explicitProtection != 1)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;
newsc->protection = protection;
newsc->explicitProtection = 1;
}
for (int i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
s->importAll(newsc);
}
if (newsc != sc)
newsc->pop();
}
void ProtDeclaration::semantic(Scope *sc)
{
if (decl)
{
semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
}
}
void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection)
{
const char *p;
switch (protection)
{
@@ -511,6 +618,12 @@ void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
break;
}
buf->writestring(p);
buf->writeByte(' ');
}
void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
protectionToCBuffer(buf, protection);
AttribDeclaration::toCBuffer(buf, hgs);
}
@@ -532,35 +645,23 @@ Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
return ad;
}
void AlignDeclaration::setScope(Scope *sc)
{
//printf("\tAlignDeclaration::setScope '%s'\n",toChars());
if (decl)
{
setScopeNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
}
}
void AlignDeclaration::semantic(Scope *sc)
{
// LDC
// we only support packed structs, as from the spec: align(1) struct Packed { ... }
// other alignments are simply ignored. my tests show this is what llvm-gcc does too ...
//printf("\tAlignDeclaration::semantic '%s'\n",toChars());
if (decl)
{ unsigned salign_save = sc->structalign;
for (unsigned i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
if (s->isStructDeclaration() && salign == 1)
{
sc->structalign = salign;
s->semantic(sc);
sc->structalign = salign_save;
}
else
{
s->semantic(sc);
}
}
sc->structalign = salign_save;
{
semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
}
else
assert(0 && "what kind of align use triggers this?");
}
@@ -577,7 +678,6 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
{
this->loc = loc;
this->isunion = isunion;
this->scope = NULL;
this->sem = 0;
}
@@ -780,6 +880,39 @@ Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
return pd;
}
void PragmaDeclaration::setScope(Scope *sc)
{
#if TARGET_NET
if (ident == Lexer::idPool("assembly"))
{
if (!args || args->dim != 1)
{
error("pragma has invalid number of arguments");
}
else
{
Expression *e = (Expression *)args->data[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->data[0] = (void *)e;
if (e->op != TOKstring)
{
error("string expected, not '%s'", e->toChars());
}
PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast<StringExp*>(e));
assert(sc);
pragma->setScope(sc);
//add to module members
assert(sc->module);
assert(sc->module->members);
sc->module->members->push(pragma);
}
}
#endif // TARGET_NET
}
void PragmaDeclaration::semantic(Scope *sc)
{ // Should be merged with PragmaStatement
@@ -803,10 +936,10 @@ void PragmaDeclaration::semantic(Scope *sc)
if (e->op == TOKstring)
{
StringExp *se = (StringExp *)e;
fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string);
fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
}
else
error("string expected for message, not '%s'", e->toChars());
fprintf(stdmsg, e->toChars());
}
fprintf(stdmsg, "\n");
}
@@ -873,6 +1006,27 @@ void PragmaDeclaration::semantic(Scope *sc)
goto Lnodecl;
}
#endif
#if TARGET_NET
else if (ident == Lexer::idPool("assembly"))
{
if (!args || args->dim != 1)
error("pragma has invalid number of arguments");
else
{
Expression *e = (Expression *)args->data[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->data[0] = (void *)e;
if (e->op != TOKstring)
{
error("string expected, not '%s'", e->toChars());
}
PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast<StringExp*>(e));
decl = new Array;
decl->push(pragma);
}
}
#endif // TARGET_NET
// LDC
#if IN_LLVM
@@ -1001,6 +1155,7 @@ void PragmaDeclaration::semantic(Scope *sc)
#endif // LDC
else if (ignoreUnsupportedPragmas)
{
if (global.params.verbose)
@@ -1298,6 +1453,37 @@ Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
return condition->include(sc, sd) ? decl : elsedecl;
}
void ConditionalDeclaration::setScope(Scope *sc)
{
Array *d = include(sc, NULL);
//printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{
Dsymbol *s = (Dsymbol *)d->data[i];
s->setScope(sc);
}
}
}
void ConditionalDeclaration::importAll(Scope *sc)
{
Array *d = include(sc, NULL);
//printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{
Dsymbol *s = (Dsymbol *)d->data[i];
s->importAll(sc);
}
}
}
void ConditionalDeclaration::addComment(unsigned char *comment)
{
@@ -1418,6 +1604,16 @@ int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
}
void StaticIfDeclaration::importAll(Scope *sc)
{
// do not evaluate condition before semantic pass
}
void StaticIfDeclaration::setScope(Scope *sc)
{
// do not evaluate condition before semantic pass
}
void StaticIfDeclaration::semantic(Scope *sc)
{
Array *d = include(sc, sd);

View File

@@ -1,183 +1,202 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ATTRIB_H
#define DMD_ATTRIB_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Expression;
struct Statement;
struct LabelDsymbol;
struct Initializer;
struct Module;
struct Condition;
#ifdef _DH
struct HdrGenState;
#endif
/**************************************************************/
struct AttribDeclaration : Dsymbol
{
Array *decl; // array of Dsymbol's
AttribDeclaration(Array *decl);
virtual Array *include(Scope *sc, ScopeDsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void addComment(unsigned char *comment);
void emitComment(Scope *sc);
const char *kind();
int oneMember(Dsymbol **ps);
int hasPointers();
void checkCtorConstInit();
void addLocalClass(ClassDeclarations *);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
AttribDeclaration *isAttribDeclaration() { return this; }
#if IN_DMD
virtual void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
#endif
#if IN_LLVM
virtual void codegen(Ir*);
#endif
};
struct StorageClassDeclaration: AttribDeclaration
{
unsigned stc;
StorageClassDeclaration(unsigned stc, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void stcToCBuffer(OutBuffer *buf, int stc);
};
struct LinkDeclaration : AttribDeclaration
{
enum LINK linkage;
LinkDeclaration(enum LINK p, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void semantic3(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *toChars();
};
struct ProtDeclaration : AttribDeclaration
{
enum PROT protection;
ProtDeclaration(enum PROT p, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct AlignDeclaration : AttribDeclaration
{
unsigned salign;
AlignDeclaration(Loc loc, unsigned sa, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct AnonDeclaration : AttribDeclaration
{
int isunion;
Scope *scope; // !=NULL means context to use
int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
};
struct PragmaDeclaration : AttribDeclaration
{
Expressions *args; // array of Expression's
PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
#endif
#if IN_LLVM
void codegen(Ir*);
#endif
};
struct ConditionalDeclaration : AttribDeclaration
{
Condition *condition;
Array *elsedecl; // array of Dsymbol's for else block
ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int oneMember(Dsymbol **ps);
void emitComment(Scope *sc);
Array *include(Scope *sc, ScopeDsymbol *s);
void addComment(unsigned char *comment);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct StaticIfDeclaration : ConditionalDeclaration
{
ScopeDsymbol *sd;
int addisdone;
StaticIfDeclaration(Condition *condition, Array *decl, Array *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
const char *kind();
};
// Mixin declarations
struct CompileDeclaration : AttribDeclaration
{
Expression *exp;
ScopeDsymbol *sd;
int compiled;
CompileDeclaration(Loc loc, Expression *exp);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
void compileIt(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif /* DMD_ATTRIB_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_ATTRIB_H
#define DMD_ATTRIB_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Expression;
struct Statement;
struct LabelDsymbol;
struct Initializer;
struct Module;
struct Condition;
#ifdef _DH
struct HdrGenState;
#endif
/**************************************************************/
struct AttribDeclaration : Dsymbol
{
Array *decl; // array of Dsymbol's
AttribDeclaration(Array *decl);
virtual Array *include(Scope *sc, ScopeDsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void setScopeNewSc(Scope *sc,
unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
void semanticNewSc(Scope *sc,
unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection,
unsigned structalign);
void semantic(Scope *sc);
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void addComment(unsigned char *comment);
void emitComment(Scope *sc);
const char *kind();
int oneMember(Dsymbol **ps);
int hasPointers();
void checkCtorConstInit();
void addLocalClass(ClassDeclarations *);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
AttribDeclaration *isAttribDeclaration() { return this; }
#if IN_DMD
virtual void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
#endif
#if IN_LLVM
virtual void codegen(Ir*);
#endif
};
struct StorageClassDeclaration: AttribDeclaration
{
unsigned stc;
StorageClassDeclaration(unsigned stc, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void stcToCBuffer(OutBuffer *buf, int stc);
};
struct LinkDeclaration : AttribDeclaration
{
enum LINK linkage;
LinkDeclaration(enum LINK p, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
void semantic3(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *toChars();
};
struct ProtDeclaration : AttribDeclaration
{
enum PROT protection;
ProtDeclaration(enum PROT p, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void importAll(Scope *sc);
void setScope(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void protectionToCBuffer(OutBuffer *buf, enum PROT protection);
};
struct AlignDeclaration : AttribDeclaration
{
unsigned salign;
AlignDeclaration(Loc loc, unsigned sa, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct AnonDeclaration : AttribDeclaration
{
int isunion;
int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
};
struct PragmaDeclaration : AttribDeclaration
{
Expressions *args; // array of Expression's
PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void setScope(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
#endif
#if IN_LLVM
void codegen(Ir*);
#endif
};
struct ConditionalDeclaration : AttribDeclaration
{
Condition *condition;
Array *elsedecl; // array of Dsymbol's for else block
ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int oneMember(Dsymbol **ps);
void emitComment(Scope *sc);
Array *include(Scope *sc, ScopeDsymbol *s);
void addComment(unsigned char *comment);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
void importAll(Scope *sc);
void setScope(Scope *sc);
};
struct StaticIfDeclaration : ConditionalDeclaration
{
ScopeDsymbol *sd;
int addisdone;
StaticIfDeclaration(Condition *condition, Array *decl, Array *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void semantic(Scope *sc);
void importAll(Scope *sc);
void setScope(Scope *sc);
const char *kind();
};
// Mixin declarations
struct CompileDeclaration : AttribDeclaration
{
Expression *exp;
ScopeDsymbol *sd;
int compiled;
CompileDeclaration(Loc loc, Expression *exp);
Dsymbol *syntaxCopy(Dsymbol *s);
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
void compileIt(Scope *sc);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif /* DMD_ATTRIB_H */

View File

@@ -1078,22 +1078,20 @@ L1:
Expression *SymOffExp::castTo(Scope *sc, Type *t)
{
Type *tb;
#if 0
printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars());
#endif
Expression *e = this;
tb = t->toBasetype();
type = type->toBasetype();
if (tb != type)
Type *tb = t->toBasetype();
Type *typeb = type->toBasetype();
if (tb != typeb)
{
// Look for pointers to functions where the functions are overloaded.
FuncDeclaration *f;
if (type->ty == Tpointer && type->next->ty == Tfunction &&
if (typeb->ty == Tpointer && typeb->next->ty == Tfunction &&
tb->ty == Tpointer && tb->next->ty == Tfunction)
{
f = var->isFuncDeclaration();
@@ -1102,15 +1100,47 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
f = f->overloadExactMatch(tb->next, m);
if (f)
{
e = new SymOffExp(loc, f, 0);
e->type = t;
#if DMDV2
if (tb->ty == Tdelegate)
{
if (f->needThis() && hasThis(sc))
{
e = new DelegateExp(loc, new ThisExp(loc), f);
e = e->semantic(sc);
}
else if (f->isNested())
{
e = new DelegateExp(loc, new IntegerExp(0), f);
e = e->semantic(sc);
}
else if (f->needThis())
{ error("no 'this' to create delegate for %s", f->toChars());
e = new ErrorExp();
}
else
{ error("cannot cast from function pointer to delegate");
e = new ErrorExp();
}
}
else
#endif
{
e = new SymOffExp(loc, f, 0);
e->type = t;
}
#if DMDV2
f->tookAddressOf++;
#endif
return e;
}
}
}
e = Expression::castTo(sc, t);
}
e->type = t;
else
{
e->type = t;
}
return e;
}
@@ -1484,13 +1514,13 @@ Expression *BinExp::typeCombine(Scope *sc)
{
assert(0);
}
else if (e1->op == TOKslice && t1->ty == Tarray &&
else if (e1->isArrayOperand() && t1->ty == Tarray &&
e2->implicitConvTo(t1->nextOf()))
{ // T[] op T
e2 = e2->castTo(sc, t1->nextOf());
t = t1->nextOf()->arrayOf();
}
else if (e2->op == TOKslice && t2->ty == Tarray &&
else if (e2->isArrayOperand() && t2->ty == Tarray &&
e1->implicitConvTo(t2->nextOf()))
{ // T op T[]
e1 = e1->castTo(sc, t2->nextOf());

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -161,6 +161,12 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
Type::typeinfoinvariant->error("%s", msg);
Type::typeinfoinvariant = this;
}
if (id == Id::TypeInfo_Shared)
{ if (Type::typeinfoshared)
Type::typeinfoshared->error("%s", msg);
Type::typeinfoshared = this;
}
#endif
}
@@ -226,19 +232,19 @@ void ClassDeclaration::semantic(Scope *sc)
//{ static int n; if (++n == 20) *(char*)0=0; }
if (!ident) // if anonymous class
{ char *id = "__anonclass";
{ const char *id = "__anonclass";
ident = Identifier::generateId(id);
}
if (!scope)
{
if (!parent && sc->parent && !sc->parent->isModule())
parent = sc->parent;
if (!sc)
sc = scope;
if (!parent && sc->parent && !sc->parent->isModule())
parent = sc->parent;
type = type->semantic(loc, sc);
handle = type;
type = type->semantic(loc, sc);
handle = handle->semantic(loc, sc);
}
if (!members) // if forward reference
{ //printf("\tclass '%s' is forward referenced\n", toChars());
return;
@@ -329,13 +335,21 @@ void ClassDeclaration::semantic(Scope *sc)
goto L7;
}
}
if (!tc->sym->symtab || tc->sym->sizeok == 0)
{ // Try to resolve forward reference
if (sc->mustsemantic && tc->sym->scope)
tc->sym->semantic(NULL);
}
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
{
//printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
//error("forward reference of base class %s", baseClass->toChars());
// Forward reference of base class, try again later
//printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
if (tc->sym->scope)
tc->sym->scope->module->addDeferredSemantic(tc->sym);
scope->module->addDeferredSemantic(this);
return;
}
@@ -389,6 +403,12 @@ void ClassDeclaration::semantic(Scope *sc)
error("inherits from duplicate interface %s", b2->base->toChars());
}
if (!tc->sym->symtab)
{ // Try to resolve forward reference
if (sc->mustsemantic && tc->sym->scope)
tc->sym->semantic(NULL);
}
b->base = tc->sym;
if (!b->base->symtab || b->base->scope)
{
@@ -397,6 +417,8 @@ void ClassDeclaration::semantic(Scope *sc)
//printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
if (tc->sym->scope)
tc->sym->scope->module->addDeferredSemantic(tc->sym);
scope->module->addDeferredSemantic(this);
return;
}
@@ -500,15 +522,15 @@ void ClassDeclaration::semantic(Scope *sc)
{ Dsymbol *s = toParent2();
if (s)
{
ClassDeclaration *cd = s->isClassDeclaration();
AggregateDeclaration *ad = s->isClassDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
if (cd || fd)
if (ad || fd)
{ isnested = 1;
Type *t;
if (cd)
t = cd->type;
if (ad)
t = ad->handle;
else if (fd)
{ AggregateDeclaration *ad = fd->isMember2();
if (ad)
@@ -564,7 +586,7 @@ void ClassDeclaration::semantic(Scope *sc)
// sc->offset += PTRSIZE; // room for uplevel context pointer
}
else
{ sc->offset = PTRSIZE * 2; // allow room for vptr[] and monitor
{ sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor
alignsize = PTRSIZE;
}
structsize = sc->offset;
@@ -703,17 +725,22 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
//buf->writestring(b->base->ident->toChars());
b->type->toCBuffer(buf, NULL, hgs);
}
buf->writenl();
buf->writeByte('{');
buf->writenl();
for (int i = 0; i < members->dim; i++)
if (members)
{
Dsymbol *s = (Dsymbol *)members->data[i];
buf->writenl();
buf->writeByte('{');
buf->writenl();
for (int i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
buf->writestring(" ");
s->toCBuffer(buf, hgs);
}
buf->writestring("}");
}
buf->writestring("}");
else
buf->writeByte(';');
buf->writenl();
}
@@ -777,13 +804,18 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
{
Dsymbol *s;
//printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
if (scope)
semantic(scope);
{ Scope *sc = scope;
sc->mustsemantic++;
semantic(sc);
sc->mustsemantic--;
}
if (!members || !symtab || scope)
{ error("is forward referenced when looking for '%s'", ident->toChars());
{
error("is forward referenced when looking for '%s'", ident->toChars());
//*(char*)0=0;
return NULL;
}
@@ -831,7 +863,7 @@ int isf(void *param, FuncDeclaration *fd)
int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
{
//printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
//printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
Dsymbol *s = search(0, fd->ident, 4|2);
if (!s)
{ //printf("not found\n");
@@ -916,6 +948,13 @@ int ClassDeclaration::isCOMinterface()
return 0;
}
#if DMDV2
int ClassDeclaration::isCPPinterface()
{
return 0;
}
#endif
/****************************************
*/
@@ -1006,10 +1045,15 @@ void InterfaceDeclaration::semantic(Scope *sc)
//printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
if (inuse)
return;
if (!scope)
{ type = type->semantic(loc, sc);
handle = handle->semantic(loc, sc);
}
if (!sc)
sc = scope;
if (!parent && sc->parent && !sc->parent->isModule())
parent = sc->parent;
type = type->semantic(loc, sc);
handle = type;
if (!members) // if forward reference
{ //printf("\tinterface '%s' is forward referenced\n", toChars());
return;
@@ -1090,6 +1134,11 @@ void InterfaceDeclaration::semantic(Scope *sc)
baseclasses.remove(i);
continue;
}
if (!b->base->symtab)
{ // Try to resolve forward reference
if (sc->mustsemantic && b->base->scope)
b->base->semantic(NULL);
}
if (!b->base->symtab || b->base->scope || b->base->inuse)
{
//error("forward reference of base class %s", baseClass->toChars());
@@ -1262,6 +1311,13 @@ int InterfaceDeclaration::isCOMinterface()
return com;
}
#if DMDV2
int InterfaceDeclaration::isCPPinterface()
{
return cpp;
}
#endif
/*******************************************
*/

View File

@@ -74,6 +74,11 @@ int ComplexExp::isConst()
return 1;
}
int NullExp::isConst()
{
return 1;
}
int SymOffExp::isConst()
{
return 2;
@@ -845,7 +850,7 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
{
cmp = e1->toComplex() == e2->toComplex();
}
else if (e1->type->isintegral())
else if (e1->type->isintegral() || e1->type->toBasetype()->ty == Tpointer)
{
cmp = (e1->toInteger() == e2->toInteger());
}
@@ -862,9 +867,13 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
Loc loc = e1->loc;
int cmp;
if (e1->op == TOKnull && e2->op == TOKnull)
if (e1->op == TOKnull)
{
cmp = 1;
cmp = (e2->op == TOKnull);
}
else if (e2->op == TOKnull)
{
cmp = 0;
}
else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
{
@@ -1046,11 +1055,12 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
return e1;
Type *tb = to->toBasetype();
Type *typeb = type->toBasetype();
// LDC: ported from D2 to allow char[] ~ char[n] arguments in CTFE
/* Allow casting from one string type to another
*/
if (e1->op == TOKstring)
{
Type *typeb = type->toBasetype();
if (tb->ty == Tarray && typeb->ty == Tarray &&
tb->nextOf()->size() == typeb->nextOf()->size())
{
@@ -1069,7 +1079,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
{ dinteger_t result;
real_t r = e1->toReal();
switch (typeb->ty)
switch (type->toBasetype()->ty)
{
case Tint8: result = (d_int8)r; break;
case Tchar:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

186
dmd/doc.c
View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -33,6 +33,7 @@
#include "hdrgen.h"
#include "doc.h"
#include "mtype.h"
#include "utf.h"
struct Escape
{
@@ -89,14 +90,18 @@ int cmp(const char *stringz, void *s, size_t slen);
int icmp(const char *stringz, void *s, size_t slen);
int isDitto(unsigned char *comment);
unsigned char *skipwhitespace(unsigned char *p);
unsigned skiptoident(OutBuffer *buf, unsigned i);
unsigned skippastident(OutBuffer *buf, unsigned i);
unsigned skippastURL(OutBuffer *buf, unsigned i);
unsigned skiptoident(OutBuffer *buf, size_t i);
unsigned skippastident(OutBuffer *buf, size_t i);
unsigned skippastURL(OutBuffer *buf, size_t i);
void highlightText(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);
Argument *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len);
int isIdStart(unsigned char *p);
int isIdTail(unsigned char *p);
int utfStride(unsigned char *p);
static unsigned char ddoc_default[] = "\
DDOC = <html><head>\n\
<META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\
@@ -238,7 +243,7 @@ void Module::gendocfile()
// Generate predefined macros
// Set the title to be the name of the module
{ char *p = toPrettyChars();
{ const char *p = toPrettyChars();
Macro::define(&macrotable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p));
}
@@ -674,7 +679,7 @@ void prefix(OutBuffer *buf, Dsymbol *s)
buf->writestring("const ");
#if DMDV2
if (d->isInvariant())
buf->writestring("invariant ");
buf->writestring("immutable ");
#endif
if (d->isFinal())
buf->writestring("final ");
@@ -948,7 +953,6 @@ void DocComment::parseSections(unsigned char *comment)
{ unsigned char *p;
unsigned char *pstart;
unsigned char *pend;
unsigned char *q;
unsigned char *idstart;
unsigned idlen;
@@ -963,17 +967,32 @@ void DocComment::parseSections(unsigned char *comment)
pstart = p;
/* Find end of section, which is ended by one of:
* 'identifier:'
* 'identifier:' (but not inside a code section)
* '\0'
*/
idlen = 0;
int inCode = 0;
while (1)
{
if (isalpha(*p) || *p == '_')
// Check for start/end of a code section
if (*p == '-')
{
q = p + 1;
while (isalnum(*q) || *q == '_')
q++;
int numdash = 0;
while (*p == '-')
{
++numdash;
p++;
}
// BUG: handle UTF PS and LS too
if (!*p || *p == '\r' || *p == '\n' && numdash >= 3)
inCode ^= 1;
}
if (!inCode && isIdStart(p))
{
unsigned char *q = p + utfStride(p);
while (isIdTail(q))
q += utfStride(q);
if (*q == ':') // identifier: ends it
{ idlen = q - p;
idstart = p;
@@ -1141,12 +1160,13 @@ void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
while (p < pend)
{
// Skip to start of macro
for (; 1; p++)
while (1)
{
switch (*p)
{
case ' ':
case '\t':
p++;
continue;
case '\n':
@@ -1154,20 +1174,18 @@ void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
goto Lcont;
default:
if (!(isalpha(*p) || *p == '_'))
{
if (namelen)
goto Ltext; // continuation of prev macro
goto Lskipline;
}
break;
if (isIdStart(p))
break;
if (namelen)
goto Ltext; // continuation of prev macro
goto Lskipline;
}
break;
}
tempstart = p;
while (isalnum(*p) || *p == '_')
p++;
while (isIdTail(p))
p += utfStride(p);
templen = p - tempstart;
while (*p == ' ' || *p == '\t')
@@ -1269,7 +1287,7 @@ void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigne
while (p < pend)
{
// Skip to start of macro
for (; 1; p++)
while (1)
{
if (p >= pend)
goto Ldone;
@@ -1277,6 +1295,7 @@ void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigne
{
case ' ':
case '\t':
p++;
continue;
case '\n':
@@ -1284,13 +1303,11 @@ void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigne
goto Lcont;
default:
if (!(isalpha(*p) || *p == '_'))
{
if (namelen)
goto Ltext; // continuation of prev macro
goto Lskipline;
}
break;
if (isIdStart(p))
break;
if (namelen)
goto Ltext; // continuation of prev macro
goto Lskipline;
}
break;
}
@@ -1300,9 +1317,9 @@ void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigne
{
if (p >= pend)
goto Ldone;
if (!(isalnum(*p) || *p == '_'))
if (!isIdTail(p))
break;
p++;
p += utfStride(p);
}
templen = p - tempstart;
@@ -1486,16 +1503,25 @@ unsigned char *skipwhitespace(unsigned char *p)
* end of buf
*/
unsigned skiptoident(OutBuffer *buf, unsigned i)
unsigned skiptoident(OutBuffer *buf, size_t i)
{
for (; i < buf->offset; i++)
{
// BUG: handle unicode alpha's
unsigned char c = buf->data[i];
if (isalpha(c) || c == '_')
break;
if (c == '\n')
while (i < buf->offset)
{ dchar_t c;
size_t oi = i;
if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c))
/* Ignore UTF errors, but still consume input
*/
break;
if (c >= 0x80)
{
if (!isUniAlpha(c))
continue;
}
else if (!(isalpha(c) || c == '_' || c == '\n'))
continue;
i = oi;
break;
}
return i;
}
@@ -1504,14 +1530,25 @@ unsigned skiptoident(OutBuffer *buf, unsigned i)
* Scan forward past end of identifier.
*/
unsigned skippastident(OutBuffer *buf, unsigned i)
unsigned skippastident(OutBuffer *buf, size_t i)
{
for (; i < buf->offset; i++)
{
// BUG: handle unicode alpha's
unsigned char c = buf->data[i];
if (!(isalnum(c) || c == '_'))
while (i < buf->offset)
{ dchar_t c;
size_t oi = i;
if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c))
/* Ignore UTF errors, but still consume input
*/
break;
if (c >= 0x80)
{
if (isUniAlpha(c))
continue;
}
else if (isalnum(c) || c == '_')
continue;
i = oi;
break;
}
return i;
}
@@ -1525,7 +1562,7 @@ unsigned skippastident(OutBuffer *buf, unsigned i)
* index just past it if it is a URL
*/
unsigned skippastURL(OutBuffer *buf, unsigned i)
unsigned skippastURL(OutBuffer *buf, size_t i)
{ unsigned length = buf->offset - i;
unsigned char *p = &buf->data[i];
unsigned j;
@@ -1810,7 +1847,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
default:
leadingBlank = 0;
if (sc && !inCode && (isalpha(c) || c == '_'))
if (sc && !inCode && isIdStart(&buf->data[i]))
{ unsigned j;
j = skippastident(buf, i);
@@ -1881,7 +1918,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset)
i = buf->insert(i, se, len);
i--; // point to ';'
}
else if (isalpha(c) || c == '_')
else if (isIdStart(&buf->data[i]))
{ unsigned j;
j = skippastident(buf, i);
@@ -2017,3 +2054,54 @@ const char *Escape::escapeChar(unsigned c)
return s;
}
/****************************************
* Determine if p points to the start of an identifier.
*/
int isIdStart(unsigned char *p)
{
unsigned c = *p;
if (isalpha(c) || c == '_')
return 1;
if (c >= 0x80)
{ size_t i = 0;
if (utf_decodeChar(p, 4, &i, &c))
return 0; // ignore errors
if (isUniAlpha(c))
return 1;
}
return 0;
}
/****************************************
* Determine if p points to the rest of an identifier.
*/
int isIdTail(unsigned char *p)
{
unsigned c = *p;
if (isalnum(c) || c == '_')
return 1;
if (c >= 0x80)
{ size_t i = 0;
if (utf_decodeChar(p, 4, &i, &c))
return 0; // ignore errors
if (isUniAlpha(c))
return 1;
}
return 0;
}
/*****************************************
* Return number of bytes in UTF character.
*/
int utfStride(unsigned char *p)
{
unsigned c = *p;
if (c < 0x80)
return 1;
size_t i = 0;
utf_decodeChar(p, 4, &i, &c); // ignore errors, but still consume input
return i;
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -28,7 +28,7 @@
#include "init.h"
#include "import.h"
#include "template.h"
#include "attrib.h"
#include "../gen/enums.h"
/****************************** Dsymbol ******************************/
@@ -45,7 +45,7 @@ Dsymbol::Dsymbol()
#endif
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
this->irsym = NULL;
@@ -64,7 +64,7 @@ Dsymbol::Dsymbol(Identifier *ident)
#endif
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
this->irsym = NULL;
@@ -164,7 +164,7 @@ char *Dsymbol::toChars()
return ident ? ident->toChars() : (char *)"__anonymous";
}
char *Dsymbol::toPrettyChars()
const char *Dsymbol::toPrettyChars()
{ Dsymbol *p;
char *s;
char *q;
@@ -190,6 +190,16 @@ char *Dsymbol::toPrettyChars()
if (q == s)
break;
q--;
#if TARGET_NET
if (AggregateDeclaration* ad = p->isAggregateDeclaration())
{
if (ad->isNested() && p->parent && p->parent->isAggregateDeclaration())
{
*q = '/';
continue;
}
}
#endif
*q = '.';
}
return s;
@@ -266,24 +276,57 @@ int Dsymbol::isAnonymous()
return ident ? 0 : 1;
}
/*************************************
* Set scope for future semantic analysis so we can
* deal better with forward references.
*/
void Dsymbol::setScope(Scope *sc)
{
//printf("Dsymbol::setScope() %p %s\n", this, toChars());
if (!sc->nofree)
sc->setNoFree(); // may need it even after semantic() finishes
scope = sc;
}
void Dsymbol::importAll(Scope *sc)
{
}
/*************************************
* Does semantic analysis on the public face of declarations.
*/
void Dsymbol::semantic(Scope *sc)
{
error("%p has no semantic routine", this);
}
/*************************************
* Does semantic analysis on initializers and members of aggregates.
*/
void Dsymbol::semantic2(Scope *sc)
{
// Most Dsymbols have no further semantic analysis needed
}
/*************************************
* Does semantic analysis on function bodies.
*/
void Dsymbol::semantic3(Scope *sc)
{
// Most Dsymbols have no further semantic analysis needed
}
/*************************************
* Look for function inlining possibilities.
*/
void Dsymbol::inlineScan()
{
// Most Dsymbols have no further semantic analysis needed
// Most Dsymbols aren't functions
}
/*********************************************
@@ -341,7 +384,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
return NULL;
}
ti->tempdecl = td;
if (!ti->semanticdone)
if (!ti->semanticRun)
ti->semantic(sc);
sm = ti->toAlias();
break;
@@ -408,6 +451,13 @@ int Dsymbol::isDeprecated()
return FALSE;
}
#if DMDV2
int Dsymbol::isOverloadable()
{
return 0;
}
#endif
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
{
return NULL;
@@ -439,7 +489,7 @@ int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
parent = sd;
if (!isAnonymous()) // no name, so can't add it to symbol table
{
if (!sd->symtab->insert(this)) // if name is already defined
if (!sd->symtabInsert(this)) // if name is already defined
{
Dsymbol *s2;
@@ -631,8 +681,8 @@ Array *Dsymbol::arraySyntaxCopy(Array *a)
void Dsymbol::addComment(unsigned char *comment)
{
// if (comment)
// printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
//if (comment)
//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
if (!this->comment)
this->comment = comment;
@@ -644,6 +694,25 @@ void Dsymbol::addComment(unsigned char *comment)
#endif
}
/********************************* OverloadSet ****************************/
#if DMDV2
OverloadSet::OverloadSet()
: Dsymbol()
{
}
void OverloadSet::push(Dsymbol *s)
{
a.push(s);
}
const char *OverloadSet::kind()
{
return "overloadset";
}
#endif
/********************************* ScopeDsymbol ****************************/
@@ -681,6 +750,7 @@ Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
//if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;
// Look in symbols declared in this module
Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
@@ -771,7 +841,7 @@ void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
{ ScopeDsymbol *ss;
ss = (ScopeDsymbol *) imports->data[i];
if (ss == s)
if (ss == s) // if already imported
{
if (protection > prots[i])
prots[i] = protection; // upgrade access
@@ -849,6 +919,73 @@ const char *ScopeDsymbol::kind()
return "ScopeDsymbol";
}
Dsymbol *ScopeDsymbol::symtabInsert(Dsymbol *s)
{
return symtab->insert(s);
}
/***************************************
* Determine number of Dsymbols, folding in AttribDeclaration members.
*/
#if DMDV2
size_t ScopeDsymbol::dim(Array *members)
{
size_t n = 0;
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
AttribDeclaration *a = s->isAttribDeclaration();
if (a)
{
n += dim(a->decl);
}
else
n++;
}
}
return n;
}
#endif
/***************************************
* Get nth Dsymbol, folding in AttribDeclaration members.
* Returns:
* Dsymbol* nth Dsymbol
* NULL not found, *pn gets incremented by the number
* of Dsymbols
*/
#if DMDV2
Dsymbol *ScopeDsymbol::getNth(Array *members, size_t nth, size_t *pn)
{
if (!members)
return NULL;
size_t n = 0;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
AttribDeclaration *a = s->isAttribDeclaration();
if (a)
{
s = getNth(a->decl, nth - n, &n);
if (s)
return s;
}
else if (n == nth)
return s;
else
n++;
}
if (pn)
*pn += n;
return NULL;
}
#endif
/*******************************************
* Look for member of the form:
@@ -938,7 +1075,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
L1:
if (td)
{
{ /* $ gives the number of elements in the tuple
*/
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
@@ -947,7 +1085,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
}
if (type)
{
{ /* $ gives the number of type entries in the type tuple
*/
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
@@ -956,22 +1095,30 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
}
if (exp->op == TOKindex)
{
{ /* array[index] where index is some function of $
*/
IndexExp *ie = (IndexExp *)exp;
pvar = &ie->lengthVar;
ce = ie->e1;
}
else if (exp->op == TOKslice)
{
{ /* array[lwr .. upr] where lwr or upr is some function of $
*/
SliceExp *se = (SliceExp *)exp;
pvar = &se->lengthVar;
ce = se->e1;
}
else
/* Didn't find $, look in enclosing scope(s).
*/
return NULL;
/* If we are indexing into an array that is really a type
* tuple, rewrite this as an index into a type tuple and
* try again.
*/
if (ce->op == TOKtype)
{
Type *t = ((TypeExp *)ce)->type;
@@ -981,8 +1128,13 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
}
}
if (!*pvar)
{
/* *pvar is lazily initialized, so if we refer to $
* multiple times, it gets set only once.
*/
if (!*pvar) // if not already initialized
{ /* Create variable v and set it to the value of $,
* which will be a constant.
*/
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
if (ce->op == TOKstring)
@@ -1030,13 +1182,12 @@ DsymbolTable::~DsymbolTable()
}
Dsymbol *DsymbolTable::lookup(Identifier *ident)
{ StringValue *sv;
{
#ifdef DEBUG
assert(ident);
assert(tab);
#endif
sv = tab->lookup((char*)ident->string, ident->len);
StringValue *sv = tab->lookup((char*)ident->string, ident->len);
return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
}

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -28,6 +28,7 @@ struct Identifier;
struct Scope;
struct DsymbolTable;
struct Declaration;
struct ThisDeclaration;
struct TupleDeclaration;
struct TypedefDeclaration;
struct AliasDeclaration;
@@ -41,6 +42,7 @@ struct FuncDeclaration;
struct FuncAliasDeclaration;
struct FuncLiteralDeclaration;
struct CtorDeclaration;
struct PostBlitDeclaration;
struct DtorDeclaration;
struct StaticCtorDeclaration;
struct StaticDtorDeclaration;
@@ -70,11 +72,13 @@ struct DeleteDeclaration;
struct HdrGenState;
struct TypeInfoDeclaration;
struct ClassInfoDeclaration;
struct OverloadSet;
#if TARGET_NET
struct PragmaScope;
#endif
#if IN_DMD
struct Symbol;
#endif
#if IN_GCC
union tree_node;
typedef union tree_node TYPE;
@@ -82,6 +86,9 @@ typedef union tree_node TYPE;
struct TYPE;
#endif
// Back end
struct Classsym;
#if IN_LLVM
class Ir;
class IrSymbol;
@@ -114,11 +121,11 @@ struct Dsymbol : Object
#endif
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
Dsymbol();
Dsymbol(Identifier *);
char *toChars();
char *toPrettyChars();
char *locToChars();
int equals(Object *o);
int isAnonymous();
@@ -136,9 +143,12 @@ struct Dsymbol : Object
static Array *arraySyntaxCopy(Array *a);
virtual const char *toPrettyChars();
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void setScope(Scope *sc);
virtual void importAll(Scope *sc);
virtual void semantic(Scope *sc);
virtual void semantic2(Scope *sc);
virtual void semantic3(Scope *sc);
@@ -152,6 +162,7 @@ struct Dsymbol : Object
#endif
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf);
virtual void toJsonBuffer(OutBuffer *buf);
virtual unsigned size(Loc loc);
virtual int isforwardRef();
virtual void defineRef(Dsymbol *s);
@@ -160,6 +171,9 @@ struct Dsymbol : Object
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
virtual int isDeprecated(); // is Dsymbol deprecated?
#if DMDV2
virtual int isOverloadable();
#endif
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
@@ -198,6 +212,7 @@ struct Dsymbol : Object
virtual TemplateInstance *isTemplateInstance() { return NULL; }
virtual TemplateMixin *isTemplateMixin() { return NULL; }
virtual Declaration *isDeclaration() { return NULL; }
virtual ThisDeclaration *isThisDeclaration() { return NULL; }
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
@@ -206,6 +221,7 @@ struct Dsymbol : Object
virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
@@ -230,6 +246,11 @@ struct Dsymbol : Object
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
#if TARGET_NET
virtual PragmaScope* isPragmaScope() { return NULL; }
#endif
#if IN_LLVM
/// Codegen traversal
virtual void codegen(Ir* ir);
@@ -250,7 +271,7 @@ struct ScopeDsymbol : Dsymbol
DsymbolTable *symtab; // members[] sorted into table
Array *imports; // imported ScopeDsymbol's
unsigned char *prots; // PROT for each import
unsigned char *prots; // array of PROT, one for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
@@ -262,9 +283,14 @@ struct ScopeDsymbol : Dsymbol
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
Dsymbol *nameCollision(Dsymbol *s);
const char *kind();
FuncDeclaration *findGetMembers();
virtual Dsymbol *symtabInsert(Dsymbol *s);
void emitMemberComments(Scope *sc);
static size_t dim(Array *members);
static Dsymbol *getNth(Array *members, size_t nth, size_t *pn = NULL);
ScopeDsymbol *isScopeDsymbol() { return this; }
};
@@ -287,6 +313,7 @@ struct ArrayScopeSymbol : ScopeDsymbol
Expression *exp; // IndexExp or SliceExp
TypeTuple *type; // for tuple[length]
TupleDeclaration *td; // for tuples of objects
Scope *sc;
ArrayScopeSymbol(Expression *e);
ArrayScopeSymbol(TypeTuple *t);
@@ -296,6 +323,20 @@ struct ArrayScopeSymbol : ScopeDsymbol
ArrayScopeSymbol *isArrayScopeSymbol() { return this; }
};
// Overload Sets
#if DMDV2
struct OverloadSet : Dsymbol
{
Dsymbols a; // array of Dsymbols
OverloadSet();
void push(Dsymbol *s);
OverloadSet *isOverloadSet() { return this; }
const char *kind();
};
#endif
// Table of Dsymbol's
struct DsymbolTable : Object

View File

@@ -1,94 +1,95 @@
// 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.
#ifndef DMD_ENUM_H
#define DMD_ENUM_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct Identifier;
struct Type;
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct EnumDeclaration : ScopeDsymbol
{
Type *type; // the TypeEnum
Type *memtype; // type of the members
#if DMDV1
dinteger_t maxval;
dinteger_t minval;
dinteger_t defaultval; // default initializer
#else
Expression *maxval;
Expression *minval;
Expression *defaultval; // default initializer
Scope *scope; // !=NULL means context to use
#endif
int isdeprecated;
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *getType();
const char *kind();
#if DMDV2
Dsymbol *search(Loc, Identifier *ident, int flags);
#endif
int isDeprecated(); // is Dsymbol deprecated?
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumDeclaration *isEnumDeclaration() { return this; }
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
void toDebug();
int cvMember(unsigned char *p);
Symbol *sinit;
Symbol *toInitializer();
#endif
#if IN_LLVM
void codegen(Ir*);
#endif
};
struct EnumMember : Dsymbol
{
Expression *value;
EnumMember(Loc loc, Identifier *id, Expression *value);
Dsymbol *syntaxCopy(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
EnumMember *isEnumMember() { return this; }
};
#endif /* DMD_ENUM_H */
// 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.
#ifndef DMD_ENUM_H
#define DMD_ENUM_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "dsymbol.h"
struct Identifier;
struct Type;
struct Expression;
#ifdef _DH
struct HdrGenState;
#endif
struct EnumDeclaration : ScopeDsymbol
{ /* enum ident : memtype { ... }
*/
Type *type; // the TypeEnum
Type *memtype; // type of the members
#if DMDV1
dinteger_t maxval;
dinteger_t minval;
dinteger_t defaultval; // default initializer
#else
Expression *maxval;
Expression *minval;
Expression *defaultval; // default initializer
#endif
int isdeprecated;
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *getType();
const char *kind();
#if DMDV2
Dsymbol *search(Loc, Identifier *ident, int flags);
#endif
int isDeprecated(); // is Dsymbol deprecated?
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
EnumDeclaration *isEnumDeclaration() { return this; }
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
void toDebug();
int cvMember(unsigned char *p);
Symbol *sinit;
Symbol *toInitializer();
#endif
#if IN_LLVM
void codegen(Ir*);
#endif
};
struct EnumMember : Dsymbol
{
Expression *value;
EnumMember(Loc loc, Identifier *id, Expression *value);
Dsymbol *syntaxCopy(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
void toDocBuffer(OutBuffer *buf);
EnumMember *isEnumMember() { return this; }
};
#endif /* DMD_ENUM_H */

View File

@@ -35,8 +35,8 @@ int isnan(double);
#endif
#include "rmem.h"
#include "port.h"
//#include "port.h"
#include "mtype.h"
#include "init.h"
#include "expression.h"
@@ -373,6 +373,11 @@ Expression *resolveProperties(Scope *sc, Expression *e)
}
}
else if (e->op == TOKdottd)
{
e = new CallExp(e->loc, e);
e = e->semantic(sc);
}
return e;
}
@@ -543,7 +548,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
size_t nparams = Argument::dim(tf->parameters);
if (nargs > nparams && tf->varargs == 0)
error(loc, "expected %zu arguments, not %zu", nparams, nargs);
error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf->toChars());
n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
@@ -568,7 +573,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
{
if (tf->varargs == 2 && i + 1 == nparams)
goto L2;
error(loc, "expected %zu arguments, not %zu", nparams, nargs);
error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
break;
}
arg = p->defaultArg;
@@ -590,7 +595,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
if (arg->implicitConvTo(p->type))
{
if (nargs != nparams)
error(loc, "expected %zu arguments, not %zu", nparams, nargs);
error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
goto L1;
}
L2:
@@ -669,7 +674,16 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
L1:
if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
arg = arg->implicitCastTo(sc, p->type);
{
if (p->type != arg->type)
{
//printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
if (arg->op == TOKtype)
arg->error("cannot pass type %s as function argument", arg->toChars());
arg = arg->implicitCastTo(sc, p->type);
arg = arg->optimize(WANTvalue);
}
}
if (p->storageClass & (STCout | STCref))
{
// BUG: should check that argument to ref is type 'invariant'
@@ -773,11 +787,15 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
{
arg = callCpCtor(loc, sc, arg);
}
#endif
// Give error for overloaded function addresses
#if DMDV2
if (arg->op == TOKsymoff)
{ SymOffExp *se = (SymOffExp *)arg;
if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
if (
se->hasOverloads &&
!se->var->isFuncDeclaration()->isUnique())
arg->error("function %s is overloaded", arg->toChars());
}
#endif
@@ -1214,10 +1232,10 @@ Expression *Expression::addressOf(Scope *sc)
Expression *Expression::deref()
{
//printf("Expression::deref()\n");
if (type->ty == Treference)
{ Expression *e;
e = new PtrExp(loc, this);
// type could be null if forward referencing an 'auto' variable
if (type && type->ty == Treference)
{
Expression *e = new PtrExp(loc, this);
e->type = ((TypeReference *)type)->next;
return e;
}
@@ -2155,6 +2173,10 @@ Lagain:
f = s->isFuncDeclaration();
if (f)
{ //printf("'%s' is a function\n", f->toChars());
if (!f->type->deco)
{
error("forward reference to %s", toChars());
}
return new VarExp(loc, f);
}
cd = s->isClassDeclaration();
@@ -2209,7 +2231,7 @@ Lagain:
TemplateInstance *ti = s->isTemplateInstance();
if (ti && !global.errors)
{ if (!ti->semanticdone)
{ if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
if (!s->isTemplateInstance())
@@ -3166,7 +3188,16 @@ Expression *StructLiteralExp::semantic(Scope *sc)
if (v->init)
{ e = v->init->toExpression();
if (!e)
error("cannot make expression out of initializer for %s", v->toChars());
{ error("cannot make expression out of initializer for %s", v->toChars());
e = new ErrorExp();
}
else if (v->scope)
{ // Do deferred semantic anaylsis
Initializer *i2 = v->init->syntaxCopy();
i2 = i2->semantic(v->scope, v->type);
e = i2->toExpression();
v->scope = NULL;
}
}
else
{ e = v->type->defaultInit();
@@ -3200,8 +3231,26 @@ Expression *StructLiteralExp::getField(Type *type, unsigned offset)
e = (Expression *)elements->data[i];
if (e)
{
e = e->copy();
e->type = type;
//printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
/* If type is a static array, and e is an initializer for that array,
* then the field initializer should be an array literal of e.
*/
if (e->type != type && type->ty == Tsarray)
{ TypeSArray *tsa = (TypeSArray *)type;
uinteger_t length = tsa->dim->toInteger();
Expressions *z = new Expressions;
z->setDim(length);
for (int q = 0; q < length; ++q)
z->data[q] = e->copy();
e = new ArrayLiteralExp(loc, z);
e->type = type;
}
else
{
e = e->copy();
e->type = type;
}
}
}
return e;
@@ -3216,20 +3265,23 @@ int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
{
/* Find which field offset is by looking at the field offsets
*/
for (size_t i = 0; i < sd->fields.dim; i++)
if (elements->dim)
{
Dsymbol *s = (Dsymbol *)sd->fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v);
for (size_t i = 0; i < sd->fields.dim; i++)
{
Dsymbol *s = (Dsymbol *)sd->fields.data[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v);
if (offset == v->offset &&
type->size() == v->type->size())
{ Expression *e = (Expression *)elements->data[i];
if (e)
{
return i;
if (offset == v->offset &&
type->size() == v->type->size())
{ Expression *e = (Expression *)elements->data[i];
if (e)
{
return i;
}
break;
}
break;
}
}
return -1;
@@ -3365,7 +3417,7 @@ Lagain:
ti = sds->isTemplateInstance();
if (ti && !global.errors)
{ Dsymbol *s;
if (!ti->semanticdone)
if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
sds2 = s->isScopeDsymbol();
@@ -3583,7 +3635,7 @@ Lagain:
else if (thisexp)
error("e.new is only for allocating nested classes");
else if (fdn)
{
{
// make sure the parent context fdn of cd is reachable from sc
for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
{
@@ -3606,7 +3658,7 @@ Lagain:
if (f)
{
assert(f);
f = f->overloadResolve(loc, arguments, sc->module);
f = f->overloadResolve(loc, NULL, arguments, sc->module);
checkDeprecated(sc, f);
member = f->isCtorDeclaration();
assert(member);
@@ -3634,7 +3686,7 @@ Lagain:
newargs = new Expressions();
newargs->shift(e);
f = cd->aggNew->overloadResolve(loc, newargs, sc->module);
f = cd->aggNew->overloadResolve(loc, NULL, newargs, sc->module);
allocator = f->isNewDeclaration();
assert(allocator);
@@ -3667,7 +3719,7 @@ Lagain:
newargs = new Expressions();
newargs->shift(e);
f = f->overloadResolve(loc, newargs, sc->module);
f = f->overloadResolve(loc, NULL, newargs, sc->module);
allocator = f->isNewDeclaration();
assert(allocator);
@@ -4200,6 +4252,7 @@ Expression *TupleExp::semantic(Scope *sc)
return (Expression *)exps->data[0];
}
type = new TypeTuple(exps);
type = type->semantic(loc, sc);
//printf("-TupleExp::semantic(%s)\n", toChars());
return this;
}
@@ -4263,13 +4316,13 @@ Expression *FuncExp::semantic(Scope *sc)
fd->parent = sc->parent;
if (global.errors)
{
if (!fd->type->next)
fd->type->next = Type::terror;
}
else
{
fd->semantic2(sc);
if (!global.errors)
if (!global.errors ||
// need to infer return type
(fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()))
{
fd->semantic3(sc);
@@ -4278,6 +4331,10 @@ Expression *FuncExp::semantic(Scope *sc)
}
}
// need to infer return type
if (global.errors && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())
((TypeFunction *)fd->type)->next = Type::terror;
// Type is a "delegate to" or "pointer to" the function literal
if (fd->isNested())
{
@@ -4377,7 +4434,13 @@ Expression *DeclarationExp::semantic(Scope *sc)
}
if (!s->isVarDeclaration())
{
declaration->semantic(sc);
Scope *sc2 = sc;
if (sc2->stc & (STCpure | STCnothrow))
sc2 = sc->push();
sc2->stc &= ~(STCpure | STCnothrow);
declaration->semantic(sc2);
if (sc2 != sc)
sc2->pop();
s->parent = sc->parent;
}
if (!global.errors)
@@ -4920,7 +4983,7 @@ Expression *BinExp::commonSemanticAssign(Scope *sc)
if (op == TOKmodass && e2->type->iscomplex())
{ error("cannot perform modulo complex arithmetic");
return new IntegerExp(0);
return new ErrorExp();
}
}
return this;
@@ -4985,6 +5048,46 @@ int BinExp::checkSideEffect(int flag)
return Expression::checkSideEffect(flag);
}
// generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
void BinExp::checkComplexMulAssign()
{
// Any multiplication by an imaginary or complex number yields a complex result.
// r *= c, i*=c, r*=i, i*=i are all forbidden operations.
const char *opstr = Token::toChars(op);
if ( e1->type->isreal() && e2->type->iscomplex())
{
error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
e1->type->toChars(), opstr, e2->type->toChars(),
e1->type->toChars(), opstr, e2->type->toChars());
}
else if (e1->type->isimaginary() && e2->type->iscomplex())
{
error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
e1->type->toChars(), opstr, e2->type->toChars(),
e1->type->toChars(), opstr, e2->type->toChars());
}
else if ((e1->type->isreal() || e1->type->isimaginary()) &&
e2->type->isimaginary())
{
error("%s %s %s is an undefined operation", e1->type->toChars(),
opstr, e2->type->toChars());
}
}
// generate an error if this is a nonsensical += or -=, eg real += imaginary
void BinExp::checkComplexAddAssign()
{
// Addition or subtraction of a real and an imaginary is a complex result.
// Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) ||
(e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex()))
)
{
error("%s %s %s is undefined (result is complex)",
e1->type->toChars(), Token::toChars(op), e2->type->toChars());
}
}
void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
expToCBuffer(buf, hgs, e1, precedence[op]);
@@ -5094,7 +5197,7 @@ Expression *FileExp::semantic(Scope *sc)
}
if (global.params.verbose)
printf("file %s\t(%s)\n", (char*)se->string, name);
printf("file %s\t(%s)\n", (char *)se->string, name);
{ File f(name);
if (f.read())
@@ -5177,7 +5280,10 @@ int AssertExp::checkSideEffect(int flag)
#if DMDV2
int AssertExp::canThrow()
{
return (global.params.useAssert != 0);
/* assert()s are non-recoverable errors, so functions that
* use them can be considered "nothrow"
*/
return 0; //(global.params.useAssert != 0);
}
#endif
@@ -5479,7 +5585,11 @@ Expression *DotIdExp::semantic(Scope *sc)
ident != Id::init && ident != Id::__sizeof &&
ident != Id::alignof && ident != Id::offsetof &&
ident != Id::mangleof && ident != Id::stringof)
{
{ /* Rewrite:
* p.ident
* as:
* (*p).ident
*/
e = new PtrExp(loc, e1);
e->type = ((TypePointer *)e1->type)->next;
return e->type->dotExp(sc, e, ident);
@@ -5598,7 +5708,7 @@ Expression *DotVarExp::semantic(Scope *sc)
type = var->type;
if (!type && global.errors)
{ // var is goofed up, just return 0
return new IntegerExp(0);
return new ErrorExp();
}
assert(type);
@@ -5935,9 +6045,10 @@ CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
: UnaExp(loc, TOKcall, sizeof(CallExp), e)
{
Expressions *arguments = new Expressions();
arguments->setDim(1);
arguments->data[0] = (void *)earg1;
if (earg1)
{ arguments->setDim(1);
arguments->data[0] = (void *)earg1;
}
this->arguments = arguments;
}
@@ -6040,7 +6151,7 @@ Expression *CallExp::semantic(Scope *sc)
if (e1->op == TOKimport && !e1->type)
{ ScopeExp *se = (ScopeExp *)e1;
TemplateInstance *ti = se->sds->isTemplateInstance();
if (ti && !ti->semanticdone)
if (ti && !ti->semanticRun)
{
/* Attempt to instantiate ti. If that works, go with it.
* If not, go with partial explicit specialization.
@@ -6067,7 +6178,7 @@ Expression *CallExp::semantic(Scope *sc)
if (e1->op == TOKdotti && !e1->type)
{ DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
TemplateInstance *ti = se->ti;
if (!ti->semanticdone)
if (!ti->semanticRun)
{
/* Attempt to instantiate ti. If that works, go with it.
* If not, go with partial explicit specialization.
@@ -6163,6 +6274,36 @@ Lagain:
if (t1->ty == Tstruct)
{
ad = ((TypeStruct *)t1)->sym;
#if DMDV2
// First look for constructor
if (ad->ctor && arguments && arguments->dim)
{
// Create variable that will get constructed
Identifier *idtmp = Lexer::uniqueId("__ctmp");
VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, NULL);
Expression *av = new DeclarationExp(loc, tmp);
av = new CommaExp(loc, av, new VarExp(loc, tmp));
Expression *e;
CtorDeclaration *cf = ad->ctor->isCtorDeclaration();
if (cf)
e = new DotVarExp(loc, av, cf, 1);
else
{ TemplateDeclaration *td = ad->ctor->isTemplateDeclaration();
assert(td);
e = new DotTemplateExp(loc, av, td);
}
e = new CallExp(loc, e, arguments);
#if !STRUCTTHISREF
/* Constructors return a pointer to the instance
*/
e = new PtrExp(loc, e);
#endif
e = e->semantic(sc);
return e;
}
#endif
// No constructor, look for overload of opCall
if (search_function(ad, Id::call))
goto L1; // overload of opCall, therefore it's a call
@@ -6205,7 +6346,7 @@ Lagain:
f = dve->var->isFuncDeclaration();
assert(f);
f = f->overloadResolve(loc, arguments, sc->module);
f = f->overloadResolve(loc, NULL, arguments, sc->module);
ad = f->toParent()->isAggregateDeclaration();
}
@@ -6306,7 +6447,7 @@ Lagain:
sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
}
f = f->overloadResolve(loc, arguments, sc->module);
f = f->overloadResolve(loc, NULL, arguments, sc->module);
checkDeprecated(sc, f);
#if DMDV2
checkPurity(sc, f);
@@ -6346,7 +6487,7 @@ Lagain:
}
f = cd->ctor;
f = f->overloadResolve(loc, arguments, sc->module);
f = f->overloadResolve(loc, NULL, arguments, sc->module);
checkDeprecated(sc, f);
#if DMDV2
checkPurity(sc, f);
@@ -6440,7 +6581,7 @@ Lagain:
}
}
f = f->overloadResolve(loc, arguments, sc->module);
f = f->overloadResolve(loc, NULL, arguments, sc->module);
checkDeprecated(sc, f);
#if DMDV2
checkPurity(sc, f);
@@ -6523,6 +6664,7 @@ int CallExp::checkSideEffect(int flag)
#if DMDV2
int CallExp::canThrow()
{
//printf("CallExp::canThrow() %s\n", toChars());
if (e1->canThrow())
return 1;
@@ -6531,10 +6673,13 @@ int CallExp::canThrow()
for (size_t i = 0; i < arguments->dim; i++)
{ Expression *e = (Expression *)arguments->data[i];
if (e->canThrow())
if (e && e->canThrow())
return 1;
}
if (global.errors && !e1->type)
return 0; // error recovery
/* If calling a function or delegate that is typed as nothrow,
* then this expression cannot throw.
* Note that pure functions can throw.
@@ -6552,8 +6697,8 @@ int CallExp::canThrow()
#if DMDV2
int CallExp::isLvalue()
{
if (type->toBasetype()->ty == Tstruct)
return 1;
// if (type->toBasetype()->ty == Tstruct)
// return 1;
Type *tb = e1->type->toBasetype();
if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
return 1; // function returns a reference
@@ -6563,12 +6708,28 @@ int CallExp::isLvalue()
Expression *CallExp::toLvalue(Scope *sc, Expression *e)
{
#if 1
if (type->toBasetype()->ty == Tstruct)
return this;
else
#endif
return Expression::toLvalue(sc, e);
}
Expression *CallExp::modifiableLvalue(Scope *sc, Expression *e)
{
#if 1
return Expression::modifiableLvalue(sc, e);
#else
/* Although function return values being usable as "ref" parameters is
* unsound, disabling it breaks existing code.
* Bugzilla 3167
*/
error("cannot assign to function call");
return toLvalue(sc, e);
#endif
}
void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ int i;
@@ -6600,8 +6761,19 @@ Expression *AddrExp::semantic(Scope *sc)
if (!e1->type)
{
error("cannot take address of %s", e1->toChars());
type = Type::tint32;
return this;
return new ErrorExp();
}
if (!e1->type->deco)
{
/* No deco means semantic() was not run on the type.
* We have to run semantic() on the symbol to get the right type:
* auto x = &bar;
* pure: int bar() { return 1;}
* otherwise the 'pure' is missing from the type assigned to x.
*/
error("forward reference to %s", e1->toChars());
return new ErrorExp();
}
type = e1->type->pointerTo();
@@ -6653,8 +6825,8 @@ Expression *AddrExp::semantic(Scope *sc)
PtrExp::PtrExp(Loc loc, Expression *e)
: UnaExp(loc, TOKstar, sizeof(PtrExp), e)
{
if (e->type)
type = ((TypePointer *)e->type)->next;
// if (e->type)
// type = ((TypePointer *)e->type)->next;
}
PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
@@ -6664,43 +6836,35 @@ PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
}
Expression *PtrExp::semantic(Scope *sc)
{ Type *tb;
{
#if LOGSEMANTIC
printf("PtrExp::semantic('%s')\n", toChars());
#endif
UnaExp::semantic(sc);
e1 = resolveProperties(sc, e1);
if (type)
return this;
if (!e1->type)
printf("PtrExp::semantic('%s')\n", toChars());
tb = e1->type->toBasetype();
switch (tb->ty)
if (!type)
{
case Tpointer:
type = tb->next;
if (type->isbit())
{ Expression *e;
UnaExp::semantic(sc);
e1 = resolveProperties(sc, e1);
if (!e1->type)
printf("PtrExp::semantic('%s')\n", toChars());
Type *tb = e1->type->toBasetype();
switch (tb->ty)
{
case Tpointer:
type = tb->next;
break;
// Rewrite *p as p[0]
e = new IndexExp(loc, e1, new IntegerExp(0));
return e->semantic(sc);
}
break;
case Tsarray:
case Tarray:
type = tb->next;
e1 = e1->castTo(sc, type->pointerTo());
break;
case Tsarray:
case Tarray:
type = tb->next;
e1 = e1->castTo(sc, type->pointerTo());
break;
default:
error("can only * a pointer, not a '%s'", e1->type->toChars());
type = Type::tint32;
break;
default:
error("can only * a pointer, not a '%s'", e1->type->toChars());
return new ErrorExp();
}
rvalue();
}
rvalue();
return this;
}
@@ -6766,7 +6930,7 @@ Expression *NegExp::semantic(Scope *sc)
return e;
e1->checkNoBool();
if (e1->op != TOKslice)
if (!e1->isArrayOperand())
e1->checkArithmetic();
type = e1->type;
}
@@ -6816,7 +6980,7 @@ Expression *ComExp::semantic(Scope *sc)
return e;
e1->checkNoBool();
if (e1->op != TOKslice)
if (!e1->isArrayOperand())
e1 = e1->checkIntegral();
type = e1->type;
}
@@ -7012,9 +7176,16 @@ Expression *CastExp::semantic(Scope *sc)
return e->implicitCastTo(sc, to);
}
if (e1->op == TOKtemplate)
{
error("cannot cast template %s to type %s", e1->toChars(), to->toChars());
return new ErrorExp();
}
Type *t1b = e1->type->toBasetype();
Type *tob = to->toBasetype();
if (tob->ty == Tstruct &&
!tob->equals(e1->type->toBasetype()) &&
!tob->equals(t1b) &&
((TypeStruct *)to)->sym->search(0, Id::call, 0)
)
{
@@ -7031,6 +7202,18 @@ Expression *CastExp::semantic(Scope *sc)
e = e->semantic(sc);
return e;
}
// Struct casts are possible only when the sizes match
if (tob->ty == Tstruct || t1b->ty == Tstruct)
{
size_t fromsize = t1b->size(loc);
size_t tosize = tob->size(loc);
if (fromsize != tosize)
{
error("cannot cast from %s to %s", e1->type->toChars(), to->toChars());
return new ErrorExp();
}
}
}
e = e1->castTo(sc, to);
return e;
@@ -7737,7 +7920,7 @@ void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
/************************************************************/
/* Can be TOKconstruct too */
/* op can be TOKassign, TOKconstruct, or TOKblit */
AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
@@ -7746,26 +7929,39 @@ AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
}
Expression *AssignExp::semantic(Scope *sc)
{ Type *t1;
{
Expression *e1old = e1;
#if LOGSEMANTIC
printf("AssignExp::semantic('%s')\n", toChars());
#endif
//printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
//printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
if (type)
return this;
if (e2->op == TOKcomma)
{ /* Rewrite to get rid of the comma from rvalue
*/
AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
ea->op = op;
Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
return e->semantic(sc);
}
/* Look for operator overloading of a[i]=value.
* Do it before semantic() otherwise the a[i] will have been
* converted to a.opIndex() already.
*/
if (e1->op == TOKarray)
{ Type *t1;
{
ArrayExp *ae = (ArrayExp *)e1;
AggregateDeclaration *ad;
Identifier *id = Id::index;
ae->e1 = ae->e1->semantic(sc);
t1 = ae->e1->type->toBasetype();
Type *t1 = ae->e1->type->toBasetype();
if (t1->ty == Tstruct)
{
ad = ((TypeStruct *)t1)->sym;
@@ -7880,13 +8076,20 @@ Expression *AssignExp::semantic(Scope *sc)
}
}
t1 = e1->type->toBasetype();
// Determine if this is an initialization of a reference
int refinit = 0;
if (op == TOKconstruct && e1->op == TOKvar)
{ VarExp *ve = (VarExp *)e1;
VarDeclaration *v = ve->var->isVarDeclaration();
if (v->storage_class & (STCout | STCref))
refinit = 1;
}
Type *t1 = e1->type->toBasetype();
if (t1->ty == Tfunction)
{ // Rewrite f=value to f(value)
Expression *e;
e = new CallExp(loc, e1, e2);
Expression *e = new CallExp(loc, e1, e2);
e = e->semantic(sc);
return e;
}
@@ -7918,7 +8121,8 @@ Expression *AssignExp::semantic(Scope *sc)
else
{ // Try to do a decent error message with the expression
// before it got constant folded
e1 = e1->modifiableLvalue(sc, e1old);
if (op != TOKconstruct)
e1 = e1->modifiableLvalue(sc, e1old);
}
if (e1->op == TOKslice &&
@@ -7930,7 +8134,7 @@ Expression *AssignExp::semantic(Scope *sc)
ismemset = 1; // make it easy for back end to tell what this is
e2 = e2->implicitCastTo(sc, t1->next);
}
else if (t1->ty == Tsarray)
else if (t1->ty == Tsarray && !refinit)
{
error("cannot assign to static array %s", e1->toChars());
}
@@ -8061,6 +8265,7 @@ Expression *AddAssignExp::semantic(Scope *sc)
typeCombine(sc);
e1->checkArithmetic();
e2->checkArithmetic();
checkComplexAddAssign();
if (type->isreal() || type->isimaginary())
{
assert(global.errors || e2->type->isfloating());
@@ -8111,6 +8316,7 @@ Expression *MinAssignExp::semantic(Scope *sc)
{
e1 = e1->checkArithmetic();
e2 = e2->checkArithmetic();
checkComplexAddAssign();
type = e1->type;
typeCombine(sc);
if (type->isreal() || type->isimaginary())
@@ -8215,6 +8421,7 @@ Expression *MulAssignExp::semantic(Scope *sc)
typeCombine(sc);
e1->checkArithmetic();
e2->checkArithmetic();
checkComplexMulAssign();
if (e2->type->isfloating())
{ Type *t1;
Type *t2;
@@ -8281,6 +8488,7 @@ Expression *DivAssignExp::semantic(Scope *sc)
typeCombine(sc);
e1->checkArithmetic();
e2->checkArithmetic();
checkComplexMulAssign();
if (e2->type->isimaginary())
{ Type *t1;
Type *t2;
@@ -8328,6 +8536,8 @@ ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
Expression *ModAssignExp::semantic(Scope *sc)
{
BinExp::semantic(sc);
checkComplexMulAssign();
return commonSemanticAssign(sc);
}
@@ -8736,10 +8946,10 @@ Expression *MulExp::semantic(Scope *sc)
return e;
typeCombine(sc);
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkArithmetic();
if (!e1->isArrayOperand())
e1->checkArithmetic();
if (!e2->isArrayOperand())
e2->checkArithmetic();
}
if (type->isfloating())
{ Type *t1 = e1->type;
Type *t2 = e2->type;
@@ -8802,10 +9012,10 @@ Expression *DivExp::semantic(Scope *sc)
return e;
typeCombine(sc);
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkArithmetic();
if (!e1->isArrayOperand())
e1->checkArithmetic();
if (!e2->isArrayOperand())
e2->checkArithmetic();
}
if (type->isfloating())
{ Type *t1 = e1->type;
Type *t2 = e2->type;
@@ -8869,10 +9079,10 @@ Expression *ModExp::semantic(Scope *sc)
return e;
typeCombine(sc);
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkArithmetic();
if (!e1->isArrayOperand())
e1->checkArithmetic();
if (!e2->isArrayOperand())
e2->checkArithmetic();
}
if (type->isfloating())
{ type = e1->type;
if (e2->type->iscomplex())
@@ -8983,10 +9193,10 @@ Expression *AndExp::semantic(Scope *sc)
else
{
typeCombine(sc);
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkIntegral();
if (!e1->isArrayOperand())
e1->checkIntegral();
if (!e2->isArrayOperand())
e2->checkIntegral();
}
}
}
return this;
@@ -9016,10 +9226,10 @@ Expression *OrExp::semantic(Scope *sc)
else
{
typeCombine(sc);
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkIntegral();
if (!e1->isArrayOperand())
e1->checkIntegral();
if (!e2->isArrayOperand())
e2->checkIntegral();
}
}
}
return this;
@@ -9049,10 +9259,10 @@ Expression *XorExp::semantic(Scope *sc)
else
{
typeCombine(sc);
if (e1->op != TOKslice && e2->op != TOKslice)
{ e1->checkIntegral();
if (!e1->isArrayOperand())
e1->checkIntegral();
if (!e2->isArrayOperand())
e2->checkIntegral();
}
}
}
return this;
@@ -9254,8 +9464,6 @@ CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
Expression *CmpExp::semantic(Scope *sc)
{ Expression *e;
Type *t1;
Type *t2;
#if LOGSEMANTIC
printf("CmpExp::semantic('%s')\n", toChars());
@@ -9265,8 +9473,10 @@ Expression *CmpExp::semantic(Scope *sc)
BinExp::semanticp(sc);
if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
Type *t1 = e1->type->toBasetype();
Type *t2 = e2->type->toBasetype();
if (t1->ty == Tclass && e2->op == TOKnull ||
t2->ty == Tclass && e1->op == TOKnull)
{
error("do not use null when comparing class types");
}
@@ -9286,6 +9496,15 @@ Expression *CmpExp::semantic(Scope *sc)
return e;
}
/* Disallow comparing T[]==T and T==T[]
*/
if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) ||
e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf()))
{
incompatibleTypes();
return new ErrorExp();
}
typeCombine(sc);
type = Type::tboolean;
@@ -9337,8 +9556,6 @@ EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
Expression *EqualExp::semantic(Scope *sc)
{ Expression *e;
Type *t1;
Type *t2;
//printf("EqualExp::semantic('%s')\n", toChars());
if (type)
@@ -9367,8 +9584,10 @@ Expression *EqualExp::semantic(Scope *sc)
}
}
if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
Type *t1 = e1->type->toBasetype();
Type *t2 = e2->type->toBasetype();
if (t1->ty == Tclass && e2->op == TOKnull ||
t2->ty == Tclass && e1->op == TOKnull)
{
error("use '%s' instead of '%s' when comparing with null",
Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
@@ -9389,6 +9608,15 @@ Expression *EqualExp::semantic(Scope *sc)
}
}
/* Disallow comparing T[]==T and T==T[]
*/
if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) ||
e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf()))
{
incompatibleTypes();
return new ErrorExp();
}
e = typeCombine(sc);
type = Type::tboolean;

View File

@@ -81,6 +81,11 @@ FuncDeclaration *hasThis(Scope *sc);
Expression *fromConstInitializer(int result, Expression *e);
int arrayExpressionCanThrow(Expressions *exps);
struct IntRange
{ uinteger_t imin;
uinteger_t imax;
};
struct Expression : Object
{
Loc loc; // file location
@@ -157,6 +162,7 @@ struct Expression : Object
// For array ops
virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
virtual Expression *buildArrayLoop(Arguments *fparams);
int isArrayOperand();
#if IN_DMD
// Back end
@@ -291,6 +297,7 @@ struct DollarExp : IdentifierExp
struct DsymbolExp : Expression
{
Dsymbol *s;
int hasOverloads;
DsymbolExp(Loc loc, Dsymbol *s);
Expression *semantic(Scope *sc);
@@ -306,6 +313,7 @@ struct ThisExp : Expression
ThisExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate);
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *toLvalue(Scope *sc, Expression *e);
@@ -343,6 +351,7 @@ struct NullExp : Expression
NullExp(Loc loc);
Expression *semantic(Scope *sc);
int isBool(int result);
int isConst();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
MATCH implicitConvTo(Type *t);
@@ -591,6 +600,7 @@ struct NewExp : Expression
Type *newtype, Expressions *arguments);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *optimize(int result);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
@@ -842,6 +852,8 @@ struct BinExp : Expression
Expression *commonSemanticAssign(Scope *sc);
Expression *commonSemanticAssignIntegral(Scope *sc);
int checkSideEffect(int flag);
void checkComplexMulAssign();
void checkComplexAddAssign();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *scaleFactor(Scope *sc);
Expression *typeCombine(Scope *sc);
@@ -1022,6 +1034,7 @@ struct CallExp : UnaExp
#endif
void scanForNestedRef(Scope *sc);
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
@@ -1182,6 +1195,8 @@ struct CastExp : UnaExp
int checkSideEffect(int flag);
void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Arguments *fparams);
#if IN_DMD
elem *toElem(IRState *irs);
#endif

6532
dmd/func.c

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,8 @@ Msgtable msgtable[] =
{ "dtor", "_dtor" },
{ "classInvariant", "__invariant" },
{ "unitTest", "_unitTest" },
{ "require", "__require" },
{ "ensure", "__ensure" },
{ "init" },
{ "size" },
{ "__sizeof", "sizeof" },
@@ -207,6 +209,10 @@ Msgtable msgtable[] =
{ "aaKeys", "_aaKeys" },
{ "aaValues", "_aaValues" },
{ "aaRehash", "_aaRehash" },
{ "monitorenter", "_d_monitorenter" },
{ "monitorexit", "_d_monitorexit" },
{ "criticalenter", "_d_criticalenter" },
{ "criticalexit", "_d_criticalexit" },
// For pragma's
{ "GNU_asm" },

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2006 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -21,6 +21,7 @@
#include "mtype.h"
#include "declaration.h"
#include "id.h"
#include "attrib.h"
/********************************* Import ****************************/
@@ -28,6 +29,7 @@ Import::Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
{
assert(id);
this->loc = loc;
this->packages = packages;
this->id = id;
@@ -84,21 +86,22 @@ Dsymbol *Import::syntaxCopy(Dsymbol *s)
void Import::load(Scope *sc)
{
DsymbolTable *dst;
Dsymbol *s;
//printf("Import::load('%s')\n", toChars());
// See if existing module
dst = Package::resolve(packages, NULL, &pkg);
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
s = dst->lookup(id);
Dsymbol *s = dst->lookup(id);
if (s)
{
#if TARGET_NET
mod = (Module *)s;
#else
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
#endif
}
if (!mod)
@@ -116,31 +119,54 @@ void Import::load(Scope *sc)
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
char* escapePath(char* fname, char* buffer, int bufLen) {
char* res = buffer;
bufLen -= 2; // for \0 and an occasional escape char
int dst = 0;
for (; dst < bufLen && *fname; ++dst, ++fname) {
switch (*fname) {
void escapePath(OutBuffer *buf, const char *fname)
{
while (1)
{
switch (*fname)
{
case 0:
return;
case '(':
case ')':
case '\\':
buffer[dst++] = '\\';
// fall through
buf->writebyte('\\');
default:
buffer[dst] = *fname;
buf->writebyte(*fname);
break;
}
fname++;
}
}
void Import::importAll(Scope *sc)
{
if (!mod)
{
load(sc);
mod->importAll(0);
if (!isstatic && !aliasId && !names.dim)
{
/* Default to private importing
*/
enum PROT prot = sc->protection;
if (!sc->explicitProtection)
prot = PROTprivate;
sc->scopesym->importScope(mod, prot);
}
}
buffer[dst] = '\0';
return buffer;
}
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s')\n", toChars());
load(sc);
// Load if not already done so
if (!mod)
{ load(sc);
mod->importAll(0);
}
if (mod)
{
@@ -158,8 +184,6 @@ void Import::semantic(Scope *sc)
//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
sc->module->aimports.push(mod);
mod->semantic();
/* Default to private importing
*/
protection = sc->protection;
@@ -171,6 +195,8 @@ void Import::semantic(Scope *sc)
sc->scopesym->importScope(mod, protection);
}
mod->semantic();
if (mod->needmoduleinfo)
sc->module->needmoduleinfo = 1;
@@ -189,67 +215,76 @@ void Import::semantic(Scope *sc)
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
if (global.params.moduleDeps != NULL)
{
/* The grammar of the file is:
* ImportDeclaration
* ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
* ModuleAliasIdentifier ] "\n"
*
* BasicImportDeclaration
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
*
* FilePath
* - any string with '(', ')' and '\' escaped with the '\' character
*/
if (global.params.moduleDeps != NULL) {
char fnameBuf[262]; // MAX_PATH+2
OutBuffer *ob = global.params.moduleDeps;
OutBuffer *const ob = global.params.moduleDeps;
ob->printf("%s (%s) : ",
sc->module->toPrettyChars(),
escapePath(sc->module->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf))
);
ob->writestring(sc->module->toPrettyChars());
ob->writestring(" (");
escapePath(ob, sc->module->srcfile->toChars());
ob->writestring(") : ");
char* protStr = "";
switch (sc->protection) {
case PROTpublic: protStr = "public"; break;
case PROTprivate: protStr = "private"; break;
case PROTpackage: protStr = "package"; break;
default: break;
}
ob->writestring(protStr);
if (isstatic) {
ob->writestring(" static");
}
ob->writestring(" : ");
ProtDeclaration::protectionToCBuffer(ob, sc->protection);
if (isstatic)
StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
ob->writestring(": ");
if (this->packages) {
for (size_t i = 0; i < this->packages->dim; i++) {
Identifier *pid = (Identifier *)this->packages->data[i];
if (packages)
{
for (size_t i = 0; i < packages->dim; i++)
{
Identifier *pid = (Identifier *)packages->data[i];
ob->printf("%s.", pid->toChars());
}
}
ob->printf("%s (%s)",
this->id->toChars(),
mod ? escapePath(mod->srcfile->toChars(), fnameBuf, sizeof(fnameBuf) / sizeof(*fnameBuf)) : "???"
);
ob->writestring(id->toChars());
ob->writestring(" (");
if (mod)
escapePath(ob, mod->srcfile->toChars());
else
ob->writestring("???");
ob->writebyte(')');
if (aliasId) {
ob->printf(" -> %s", aliasId->toChars());
} else {
if (names.dim > 0) {
ob->writestring(" : ");
for (size_t i = 0; i < names.dim; i++)
{
if (i > 0) {
ob->writebyte(',');
}
for (size_t i = 0; i < names.dim; i++)
{
if (i == 0)
ob->writebyte(':');
else
ob->writebyte(',');
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
Identifier *name = (Identifier *)names.data[i];
Identifier *alias = (Identifier *)aliases.data[i];
if (!alias) {
ob->printf("%s", name->toChars());
alias = name;
} else {
ob->printf("%s=%s", alias->toChars(), name->toChars());
}
}
if (!alias)
{
ob->printf("%s", name->toChars());
alias = name;
}
else
ob->printf("%s=%s", alias->toChars(), name->toChars());
}
if (aliasId)
ob->printf(" -> %s", aliasId->toChars());
ob->writenl();
}
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
void Import::semantic2(Scope *sc)

View File

@@ -1,67 +1,68 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_IMPORT_H
#define DMD_IMPORT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Identifier;
struct Scope;
struct OutBuffer;
struct Module;
struct Package;
struct AliasDeclaration;
#ifdef _DH
struct HdrGenState;
#endif
struct Import : Dsymbol
{
Array *packages; // array of Identifier's representing packages
Identifier *id; // module Identifier
Identifier *aliasId;
int isstatic; // !=0 if static import
enum PROT protection;
// Pairs of alias=name to bind into current namespace
Array names;
Array aliases;
Array aliasdecls; // AliasDeclarations for names/aliases
Module *mod;
Package *pkg; // leftmost package/module
Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic);
void addAlias(Identifier *name, Identifier *alias);
const char *kind();
enum PROT prot();
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
void load(Scope *sc);
void semantic(Scope *sc);
void semantic2(Scope *sc);
Dsymbol *toAlias();
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Import *isImport() { return this; }
};
#endif /* DMD_IMPORT_H */
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_IMPORT_H
#define DMD_IMPORT_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "dsymbol.h"
struct Identifier;
struct Scope;
struct OutBuffer;
struct Module;
struct Package;
struct AliasDeclaration;
#ifdef _DH
struct HdrGenState;
#endif
struct Import : Dsymbol
{
Array *packages; // array of Identifier's representing packages
Identifier *id; // module Identifier
Identifier *aliasId;
int isstatic; // !=0 if static import
enum PROT protection;
// Pairs of alias=name to bind into current namespace
Array names;
Array aliases;
Array aliasdecls; // AliasDeclarations for names/aliases
Module *mod;
Package *pkg; // leftmost package/module
Import(Loc loc, Array *packages, Identifier *id, Identifier *aliasId,
int isstatic);
void addAlias(Identifier *name, Identifier *alias);
const char *kind();
enum PROT prot();
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
void load(Scope *sc);
void importAll(Scope *sc);
void semantic(Scope *sc);
void semantic2(Scope *sc);
Dsymbol *toAlias();
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Import *isImport() { return this; }
};
#endif /* DMD_IMPORT_H */

View File

@@ -396,32 +396,89 @@ Expression *ArrayInitializer::toExpression()
{ Expressions *elements;
Expression *e;
//printf("ArrayInitializer::toExpression()\n");
//printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
//static int i; if (++i == 2) halt();
size_t edim;
Type *t = NULL;
if (type)
{
if (type == Type::terror)
return new ErrorExp();
t = type->toBasetype();
switch (t->ty)
{
case Tsarray:
edim = ((TypeSArray *)t)->dim->toInteger();
break;
case Tpointer:
case Tarray:
edim = dim;
break;
default:
assert(0);
}
}
else
{
edim = value.dim;
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index.data[i])
j = ((Expression *)index.data[i])->toInteger();
if (j >= edim)
edim = j + 1;
}
}
elements = new Expressions();
for (size_t i = 0; i < value.dim; i++)
elements->setDim(edim);
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index.data[i])
goto Lno;
j = ((Expression *)index.data[i])->toInteger();
assert(j < edim);
Initializer *iz = (Initializer *)value.data[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
{
goto Lno;
elements->push(ex);
}
elements->data[j] = ex;
}
e = new ArrayLiteralExp(loc, elements);
/* Fill in any missing elements with the default initializer
*/
{
Expression *init = NULL;
for (size_t i = 0; i < edim; i++)
{
if (!elements->data[i])
{
if (!type)
goto Lno;
if (!init)
init = t->next->defaultInit();
elements->data[i] = init;
}
}
Expression *e = new ArrayLiteralExp(loc, elements);
e->type = type;
return e;
}
Lno:
delete elements;
error(loc, "array initializers as expressions are not allowed");
return NULL;
return new ErrorExp();
}
/********************************
* If possible, convert array initializer to associative array initializer.
*/
@@ -469,7 +526,7 @@ Type *ArrayInitializer::inferType(Scope *sc)
for (size_t i = 0; i < value.dim; i++)
{
if (index.data[i])
goto Lno;
goto Laa;
}
if (value.dim)
{
@@ -482,9 +539,21 @@ Type *ArrayInitializer::inferType(Scope *sc)
}
}
Lno:
error(loc, "cannot infer type from this array initializer");
return Type::terror;
Laa:
/* It's possibly an associative array initializer
*/
Initializer *iz = (Initializer *)value.data[0];
Expression *indexinit = (Expression *)index.data[0];
if (iz && indexinit)
{ Type *t = iz->inferType(sc);
indexinit = indexinit->semantic(sc);
Type *indext = indexinit->type;
t = new TypeAArray(t, indext);
type = t->semantic(loc, sc);
}
else
error(loc, "cannot infer type from this array initializer");
return type;
}
@@ -569,14 +638,27 @@ Type *ExpInitializer::inferType(Scope *sc)
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
#if DMDV2
// Give error for overloaded function addresses
if (exp->op == TOKsymoff)
{ SymOffExp *se = (SymOffExp *)exp;
if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
if (
#if DMDV2
se->hasOverloads &&
#else
se->var->isFuncDeclaration() &&
#endif
!se->var->isFuncDeclaration()->isUnique())
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
}
// Give error for overloaded function addresses
if (exp->op == TOKdelegate)
{ DelegateExp *se = (DelegateExp *)exp;
if (
se->func->isFuncDeclaration() &&
!se->func->isFuncDeclaration()->isUnique())
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
}
#endif
Type *t = exp->type;
if (!t)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1266,7 +1266,9 @@ unsigned Lexer::escapeSequence()
}
}
if (ndigits != 2 && !utf_isValidDchar(v))
error("invalid UTF character \\U%08x", v);
{ error("invalid UTF character \\U%08x", v);
v = '?'; // recover with valid UTF character
}
c = v;
}
else
@@ -3071,6 +3073,7 @@ void Lexer::initKeywords()
Token::tochars[TOKidentifier] = "identifier";
// For debugging
Token::tochars[TOKerror] = "error";
Token::tochars[TOKdotexp] = "dotexp";
Token::tochars[TOKdotti] = "dotti";
Token::tochars[TOKdotvar] = "dotvar";

View File

@@ -1,305 +1,307 @@
// 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.
#ifndef DMD_LEXER_H
#define DMD_LEXER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "mars.h"
struct StringTable;
struct Identifier;
struct Module;
/* Tokens:
( )
[ ]
{ }
< > <= >= == != === !==
<< >> <<= >>= >>> >>>=
+ - += -=
* / % *= /= %=
& | ^ &= |= ^=
= ! ~
++ --
. -> : ,
? && ||
*/
enum TOK
{
TOKreserved,
// Other
TOKlparen, TOKrparen,
TOKlbracket, TOKrbracket,
TOKlcurly, TOKrcurly,
TOKcolon, TOKneg,
TOKsemicolon, TOKdotdotdot,
TOKeof, TOKcast,
TOKnull, TOKassert,
TOKtrue, TOKfalse,
TOKarray, TOKcall,
TOKaddress,
TOKtype, TOKthrow,
TOKnew, TOKdelete,
TOKstar, TOKsymoff,
TOKvar, TOKdotvar,
TOKdotti, TOKdotexp,
TOKdottype, TOKslice,
TOKarraylength, TOKversion,
TOKmodule, TOKdollar,
TOKtemplate, TOKdottd,
TOKdeclaration, TOKtypeof,
TOKpragma, TOKdsymbol,
TOKtypeid, TOKuadd,
TOKremove,
TOKnewanonclass, TOKcomment,
TOKarrayliteral, TOKassocarrayliteral,
TOKstructliteral,
// Operators
TOKlt, TOKgt,
TOKle, TOKge,
TOKequal, TOKnotequal,
TOKidentity, TOKnotidentity,
TOKindex, TOKis,
TOKtobool,
// 60
// NCEG floating point compares
// !<>= <> <>= !> !>= !< !<= !<>
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
TOKshl, TOKshr,
TOKshlass, TOKshrass,
TOKushr, TOKushrass,
TOKcat, TOKcatass, // ~ ~=
TOKadd, TOKmin, TOKaddass, TOKminass,
TOKmul, TOKdiv, TOKmod,
TOKmulass, TOKdivass, TOKmodass,
TOKand, TOKor, TOKxor,
TOKandass, TOKorass, TOKxorass,
TOKassign, TOKnot, TOKtilde,
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror,
// 104
// Numeric literals
TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v,
TOKfloat32v, TOKfloat64v, TOKfloat80v,
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
// Char constants
TOKcharv, TOKwcharv, TOKdcharv,
// Leaf operators
TOKidentifier, TOKstring,
TOKthis, TOKsuper,
TOKhalt, TOKtuple,
// Basic types
TOKvoid,
TOKint8, TOKuns8,
TOKint16, TOKuns16,
TOKint32, TOKuns32,
TOKint64, TOKuns64,
TOKfloat32, TOKfloat64, TOKfloat80,
TOKimaginary32, TOKimaginary64, TOKimaginary80,
TOKcomplex32, TOKcomplex64, TOKcomplex80,
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKcent, TOKucent,
// Aggregates
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
TOKmixin,
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
TOKauto, TOKpackage, TOKmanifest,
// Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
TOKasm, TOKforeach, TOKforeach_reverse,
TOKscope,
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
// Contracts
TOKbody, TOKinvariant,
// Testing
TOKunittest,
// Added after 1.0
TOKref,
TOKmacro,
#if DMDV2
TOKtraits,
TOKoverloadset,
TOKpure,
TOKnothrow,
TOKtls,
TOKline,
TOKfile,
TOKshared,
#endif
// LDC specific
#if IN_LLVM
TOKgep,
#endif
TOKMAX
};
#define CASE_BASIC_TYPES \
case TOKwchar: case TOKdchar: \
case TOKbit: case TOKbool: case TOKchar: \
case TOKint8: case TOKuns8: \
case TOKint16: case TOKuns16: \
case TOKint32: case TOKuns32: \
case TOKint64: case TOKuns64: \
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
case TOKvoid
#define CASE_BASIC_TYPES_X(t) \
case TOKvoid: t = Type::tvoid; goto LabelX; \
case TOKint8: t = Type::tint8; goto LabelX; \
case TOKuns8: t = Type::tuns8; goto LabelX; \
case TOKint16: t = Type::tint16; goto LabelX; \
case TOKuns16: t = Type::tuns16; goto LabelX; \
case TOKint32: t = Type::tint32; goto LabelX; \
case TOKuns32: t = Type::tuns32; goto LabelX; \
case TOKint64: t = Type::tint64; goto LabelX; \
case TOKuns64: t = Type::tuns64; goto LabelX; \
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
case TOKbit: t = Type::tbit; goto LabelX; \
case TOKbool: t = Type::tbool; goto LabelX; \
case TOKchar: t = Type::tchar; goto LabelX; \
case TOKwchar: t = Type::twchar; goto LabelX; \
case TOKdchar: t = Type::tdchar; goto LabelX; \
LabelX
struct Token
{
Token *next;
unsigned char *ptr; // pointer to first character of this token within buffer
enum TOK value;
unsigned char *blockComment; // doc comment string prior to this token
unsigned char *lineComment; // doc comment for previous token
union
{
// Integers
d_int64 int64value;
d_uns64 uns64value;
// Floats
#ifdef IN_GCC
// real_t float80value; // can't use this in a union!
#else
d_float80 float80value;
#endif
struct
{ unsigned char *ustring; // UTF8 string
unsigned len;
unsigned char postfix; // 'c', 'w', 'd'
};
Identifier *ident;
};
#ifdef IN_GCC
real_t float80value; // can't use this in a union!
#endif
static const char *tochars[TOKMAX];
static void *operator new(size_t sz);
int isKeyword();
void print();
const char *toChars();
static const char *toChars(enum TOK);
};
struct Lexer
{
static StringTable stringtable;
static OutBuffer stringbuffer;
static Token *freelist;
Loc loc; // for error messages
unsigned char *base; // pointer to start of buffer
unsigned char *end; // past end of buffer
unsigned char *p; // current character
Token token;
Module *mod;
int doDocComment; // collect doc comment information
int anyToken; // !=0 means seen at least one token
int commentToken; // !=0 means comments are TOKcomment's
Lexer(Module *mod,
unsigned char *base, unsigned begoffset, unsigned endoffset,
int doDocComment, int commentToken);
static void initKeywords();
static Identifier *idPool(const char *s);
static Identifier *uniqueId(const char *s);
static Identifier *uniqueId(const char *s, int num);
TOK nextToken();
TOK peekNext();
void scan(Token *t);
Token *peek(Token *t);
Token *peekPastParen(Token *t);
unsigned escapeSequence();
TOK wysiwygStringConstant(Token *t, int tc);
TOK hexStringConstant(Token *t);
#if DMDV2
TOK delimitedStringConstant(Token *t);
TOK tokenStringConstant(Token *t);
#endif
TOK escapeStringConstant(Token *t, int wide);
TOK charConstant(Token *t, int wide);
void stringPostfix(Token *t);
unsigned wchar(unsigned u);
TOK number(Token *t);
TOK inreal(Token *t);
void error(const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void pragma();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
static int isValidIdentifier(char *p);
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
};
#endif /* DMD_LEXER_H */
// 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.
#ifndef DMD_LEXER_H
#define DMD_LEXER_H
#ifdef __DMC__
#pragma once
#endif /* __DMC__ */
#include "root.h"
#include "mars.h"
struct StringTable;
struct Identifier;
struct Module;
/* Tokens:
( )
[ ]
{ }
< > <= >= == != === !==
<< >> <<= >>= >>> >>>=
+ - += -=
* / % *= /= %=
& | ^ &= |= ^=
= ! ~
++ --
. -> : ,
? && ||
*/
enum TOK
{
TOKreserved,
// Other
TOKlparen, TOKrparen,
TOKlbracket, TOKrbracket,
TOKlcurly, TOKrcurly,
TOKcolon, TOKneg,
TOKsemicolon, TOKdotdotdot,
TOKeof, TOKcast,
TOKnull, TOKassert,
TOKtrue, TOKfalse,
TOKarray, TOKcall,
TOKaddress,
TOKtype, TOKthrow,
TOKnew, TOKdelete,
TOKstar, TOKsymoff,
TOKvar, TOKdotvar,
TOKdotti, TOKdotexp,
TOKdottype, TOKslice,
TOKarraylength, TOKversion,
TOKmodule, TOKdollar,
TOKtemplate, TOKdottd,
TOKdeclaration, TOKtypeof,
TOKpragma, TOKdsymbol,
TOKtypeid, TOKuadd,
TOKremove,
TOKnewanonclass, TOKcomment,
TOKarrayliteral, TOKassocarrayliteral,
TOKstructliteral,
// Operators
TOKlt, TOKgt,
TOKle, TOKge,
TOKequal, TOKnotequal,
TOKidentity, TOKnotidentity,
TOKindex, TOKis,
TOKtobool,
// 60
// NCEG floating point compares
// !<>= <> <>= !> !>= !< !<= !<>
TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
TOKshl, TOKshr,
TOKshlass, TOKshrass,
TOKushr, TOKushrass,
TOKcat, TOKcatass, // ~ ~=
TOKadd, TOKmin, TOKaddass, TOKminass,
TOKmul, TOKdiv, TOKmod,
TOKmulass, TOKdivass, TOKmodass,
TOKand, TOKor, TOKxor,
TOKandass, TOKorass, TOKxorass,
TOKassign, TOKnot, TOKtilde,
TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror,
// 104
// Numeric literals
TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v,
TOKfloat32v, TOKfloat64v, TOKfloat80v,
TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
// Char constants
TOKcharv, TOKwcharv, TOKdcharv,
// Leaf operators
TOKidentifier, TOKstring,
TOKthis, TOKsuper,
TOKhalt, TOKtuple,
TOKerror,
// Basic types
TOKvoid,
TOKint8, TOKuns8,
TOKint16, TOKuns16,
TOKint32, TOKuns32,
TOKint64, TOKuns64,
TOKfloat32, TOKfloat64, TOKfloat80,
TOKimaginary32, TOKimaginary64, TOKimaginary80,
TOKcomplex32, TOKcomplex64, TOKcomplex80,
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKcent, TOKucent,
// 150
// Aggregates
TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
TOKmixin,
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
TOKauto, TOKpackage, TOKmanifest,
// Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
TOKasm, TOKforeach, TOKforeach_reverse,
TOKscope,
TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
// Contracts
TOKbody, TOKinvariant,
// Testing
TOKunittest,
// Added after 1.0
TOKref,
TOKmacro,
#if DMDV2
TOKtraits,
TOKoverloadset,
TOKpure,
TOKnothrow,
TOKtls,
TOKline,
TOKfile,
TOKshared,
#endif
// LDC specific
#if IN_LLVM
TOKgep,
#endif
TOKMAX
};
#define CASE_BASIC_TYPES \
case TOKwchar: case TOKdchar: \
case TOKbit: case TOKbool: case TOKchar: \
case TOKint8: case TOKuns8: \
case TOKint16: case TOKuns16: \
case TOKint32: case TOKuns32: \
case TOKint64: case TOKuns64: \
case TOKfloat32: case TOKfloat64: case TOKfloat80: \
case TOKimaginary32: case TOKimaginary64: case TOKimaginary80: \
case TOKcomplex32: case TOKcomplex64: case TOKcomplex80: \
case TOKvoid
#define CASE_BASIC_TYPES_X(t) \
case TOKvoid: t = Type::tvoid; goto LabelX; \
case TOKint8: t = Type::tint8; goto LabelX; \
case TOKuns8: t = Type::tuns8; goto LabelX; \
case TOKint16: t = Type::tint16; goto LabelX; \
case TOKuns16: t = Type::tuns16; goto LabelX; \
case TOKint32: t = Type::tint32; goto LabelX; \
case TOKuns32: t = Type::tuns32; goto LabelX; \
case TOKint64: t = Type::tint64; goto LabelX; \
case TOKuns64: t = Type::tuns64; goto LabelX; \
case TOKfloat32: t = Type::tfloat32; goto LabelX; \
case TOKfloat64: t = Type::tfloat64; goto LabelX; \
case TOKfloat80: t = Type::tfloat80; goto LabelX; \
case TOKimaginary32: t = Type::timaginary32; goto LabelX; \
case TOKimaginary64: t = Type::timaginary64; goto LabelX; \
case TOKimaginary80: t = Type::timaginary80; goto LabelX; \
case TOKcomplex32: t = Type::tcomplex32; goto LabelX; \
case TOKcomplex64: t = Type::tcomplex64; goto LabelX; \
case TOKcomplex80: t = Type::tcomplex80; goto LabelX; \
case TOKbit: t = Type::tbit; goto LabelX; \
case TOKbool: t = Type::tbool; goto LabelX; \
case TOKchar: t = Type::tchar; goto LabelX; \
case TOKwchar: t = Type::twchar; goto LabelX; \
case TOKdchar: t = Type::tdchar; goto LabelX; \
LabelX
struct Token
{
Token *next;
unsigned char *ptr; // pointer to first character of this token within buffer
enum TOK value;
unsigned char *blockComment; // doc comment string prior to this token
unsigned char *lineComment; // doc comment for previous token
union
{
// Integers
d_int64 int64value;
d_uns64 uns64value;
// Floats
#ifdef IN_GCC
// real_t float80value; // can't use this in a union!
#else
d_float80 float80value;
#endif
struct
{ unsigned char *ustring; // UTF8 string
unsigned len;
unsigned char postfix; // 'c', 'w', 'd'
};
Identifier *ident;
};
#ifdef IN_GCC
real_t float80value; // can't use this in a union!
#endif
static const char *tochars[TOKMAX];
static void *operator new(size_t sz);
int isKeyword();
void print();
const char *toChars();
static const char *toChars(enum TOK);
};
struct Lexer
{
static StringTable stringtable;
static OutBuffer stringbuffer;
static Token *freelist;
Loc loc; // for error messages
unsigned char *base; // pointer to start of buffer
unsigned char *end; // past end of buffer
unsigned char *p; // current character
Token token;
Module *mod;
int doDocComment; // collect doc comment information
int anyToken; // !=0 means seen at least one token
int commentToken; // !=0 means comments are TOKcomment's
Lexer(Module *mod,
unsigned char *base, unsigned begoffset, unsigned endoffset,
int doDocComment, int commentToken);
static void initKeywords();
static Identifier *idPool(const char *s);
static Identifier *uniqueId(const char *s);
static Identifier *uniqueId(const char *s, int num);
TOK nextToken();
TOK peekNext();
void scan(Token *t);
Token *peek(Token *t);
Token *peekPastParen(Token *t);
unsigned escapeSequence();
TOK wysiwygStringConstant(Token *t, int tc);
TOK hexStringConstant(Token *t);
#if DMDV2
TOK delimitedStringConstant(Token *t);
TOK tokenStringConstant(Token *t);
#endif
TOK escapeStringConstant(Token *t, int wide);
TOK charConstant(Token *t, int wide);
void stringPostfix(Token *t);
unsigned wchar(unsigned u);
TOK number(Token *t);
TOK inreal(Token *t);
void error(const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void pragma();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
static int isValidIdentifier(char *p);
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
};
#endif /* DMD_LEXER_H */

View File

@@ -1,292 +1,297 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "root.h"
#include "init.h"
#include "declaration.h"
#include "aggregate.h"
#include "mtype.h"
#include "attrib.h"
#include "template.h"
#include "id.h"
#include "module.h"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
char *cpp_mangle(Dsymbol *s);
#endif
char *mangle(Declaration *sthis)
{
OutBuffer buf;
char *id;
Dsymbol *s;
//printf("::mangle(%s)\n", sthis->toChars());
s = sthis;
do
{
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
if (s->ident)
{
FuncDeclaration *fd = s->isFuncDeclaration();
if (s != sthis && fd)
{
id = mangle(fd);
buf.prependstring(id);
goto L1;
}
else
{
id = s->ident->toChars();
int len = strlen(id);
char tmp[sizeof(len) * 3 + 1];
buf.prependstring(id);
sprintf(tmp, "%d", len);
buf.prependstring(tmp);
}
}
else
buf.prependstring("0");
s = s->parent;
} while (s);
// buf.prependstring("_D");
L1:
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
//printf("sthis->type = %s\n", sthis->type->toChars());
FuncDeclaration *fd = sthis->isFuncDeclaration();
if (fd && (fd->needThis() || fd->isNested()))
buf.writeByte(Type::needThisPrefix());
if (sthis->type->deco)
buf.writestring(sthis->type->deco);
else
{ assert(fd->inferRetType);
}
id = buf.toChars();
buf.data = NULL;
return id;
}
char *Declaration::mangle()
#if __DMC__
__out(result)
{
int len = strlen(result);
assert(len > 0);
//printf("mangle: '%s' => '%s'\n", toChars(), result);
for (int i = 0; i < len; i++)
{
assert(result[i] == '_' ||
result[i] == '@' ||
isalnum(result[i]) || result[i] & 0x80);
}
}
__body
#endif
{
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
if (!parent || parent->isModule()) // if at global scope
{
// If it's not a D declaration, no mangling
switch (linkage)
{
case LINKd:
break;
// LDC
case LINKintrinsic:
case LINKc:
case LINKwindows:
case LINKpascal:
return ident->toChars();
case LINKcpp:
#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
return cpp_mangle(this);
#else
// Windows C++ mangling is done by C++ back end
return ident->toChars();
#endif
case LINKdefault:
error("forward declaration");
return ident->toChars();
default:
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
assert(0);
}
}
char *p = ::mangle(this);
OutBuffer buf;
buf.writestring("_D");
buf.writestring(p);
p = buf.toChars();
buf.data = NULL;
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
return p;
}
char *FuncDeclaration::mangle()
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
if (isMain())
return (char *)"_Dmain";
if (isWinMain() || isDllMain())
return ident->toChars();
assert(this);
return Declaration::mangle();
}
char *StructDeclaration::mangle()
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *TypedefDeclaration::mangle()
{
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *ClassDeclaration::mangle()
{
Dsymbol *parentsave = parent;
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
/* These are reserved to the compiler, so keep simple
* names for them.
*/
if (ident == Id::Exception)
{ if (parent->ident == Id::object)
parent = NULL;
}
else if (ident == Id::TypeInfo ||
// ident == Id::Exception ||
ident == Id::TypeInfo_Struct ||
ident == Id::TypeInfo_Class ||
ident == Id::TypeInfo_Typedef ||
ident == Id::TypeInfo_Tuple ||
this == object ||
this == classinfo ||
this == Module::moduleinfo ||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
)
parent = NULL;
char *id = Dsymbol::mangle();
parent = parentsave;
return id;
}
char *TemplateInstance::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateInstance::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (!tempdecl)
error("is not defined");
else if (tempdecl->parent)
{
char *p = tempdecl->parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
return id;
}
char *TemplateMixin::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateMixin::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
return id;
}
char *Dsymbol::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("Dsymbol::mangle() '%s'", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
return id;
}
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "root.h"
#include "init.h"
#include "declaration.h"
#include "aggregate.h"
#include "mtype.h"
#include "attrib.h"
#include "template.h"
#include "id.h"
#include "module.h"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
char *cpp_mangle(Dsymbol *s);
#endif
char *mangle(Declaration *sthis)
{
OutBuffer buf;
char *id;
Dsymbol *s;
//printf("::mangle(%s)\n", sthis->toChars());
s = sthis;
do
{
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
if (s->ident)
{
FuncDeclaration *fd = s->isFuncDeclaration();
if (s != sthis && fd)
{
id = mangle(fd);
buf.prependstring(id);
goto L1;
}
else
{
id = s->ident->toChars();
int len = strlen(id);
char tmp[sizeof(len) * 3 + 1];
buf.prependstring(id);
sprintf(tmp, "%d", len);
buf.prependstring(tmp);
}
}
else
buf.prependstring("0");
s = s->parent;
} while (s);
// buf.prependstring("_D");
L1:
//printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
//printf("sthis->type = %s\n", sthis->type->toChars());
FuncDeclaration *fd = sthis->isFuncDeclaration();
if (fd && (fd->needThis() || fd->isNested()))
buf.writeByte(Type::needThisPrefix());
if (sthis->type->deco)
buf.writestring(sthis->type->deco);
else
{
#ifdef DEBUG
if (!fd->inferRetType)
printf("%s\n", fd->toChars());
#endif
assert(fd && fd->inferRetType);
}
id = buf.toChars();
buf.data = NULL;
return id;
}
char *Declaration::mangle()
#if __DMC__
__out(result)
{
int len = strlen(result);
assert(len > 0);
//printf("mangle: '%s' => '%s'\n", toChars(), result);
for (int i = 0; i < len; i++)
{
assert(result[i] == '_' ||
result[i] == '@' ||
isalnum(result[i]) || result[i] & 0x80);
}
}
__body
#endif
{
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
if (!parent || parent->isModule()) // if at global scope
{
// If it's not a D declaration, no mangling
switch (linkage)
{
case LINKd:
break;
// LDC
case LINKintrinsic:
case LINKc:
case LINKwindows:
case LINKpascal:
return ident->toChars();
case LINKcpp:
#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
return cpp_mangle(this);
#else
// Windows C++ mangling is done by C++ back end
return ident->toChars();
#endif
case LINKdefault:
error("forward declaration");
return ident->toChars();
default:
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
assert(0);
}
}
char *p = ::mangle(this);
OutBuffer buf;
buf.writestring("_D");
buf.writestring(p);
p = buf.toChars();
buf.data = NULL;
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
return p;
}
char *FuncDeclaration::mangle()
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
if (isMain())
return (char *)"_Dmain";
if (isWinMain() || isDllMain())
return ident->toChars();
assert(this);
return Declaration::mangle();
}
char *StructDeclaration::mangle()
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *TypedefDeclaration::mangle()
{
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle();
}
char *ClassDeclaration::mangle()
{
Dsymbol *parentsave = parent;
//printf("ClassDeclaration::mangle() %s.%s\n", parent->toChars(), toChars());
/* These are reserved to the compiler, so keep simple
* names for them.
*/
if (ident == Id::Exception)
{ if (parent->ident == Id::object)
parent = NULL;
}
else if (ident == Id::TypeInfo ||
// ident == Id::Exception ||
ident == Id::TypeInfo_Struct ||
ident == Id::TypeInfo_Class ||
ident == Id::TypeInfo_Typedef ||
ident == Id::TypeInfo_Tuple ||
this == object ||
this == classinfo ||
this == Module::moduleinfo ||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
)
parent = NULL;
char *id = Dsymbol::mangle();
parent = parentsave;
return id;
}
char *TemplateInstance::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateInstance::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (!tempdecl)
error("is not defined");
else if (tempdecl->parent)
{
char *p = tempdecl->parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
return id;
}
char *TemplateMixin::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("TemplateMixin::mangle() %s", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateMixin::mangle() %s = %s\n", toChars(), id);
return id;
}
char *Dsymbol::mangle()
{
OutBuffer buf;
char *id;
#if 0
printf("Dsymbol::mangle() '%s'", toChars());
if (parent)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
return id;
}

View File

@@ -32,6 +32,7 @@
#include "cond.h"
#include "expression.h"
#include "lexer.h"
#include "json.h"
#include "gen/revisions.h"
@@ -44,6 +45,7 @@ Global::Global()
hdr_ext = "di";
doc_ext = "html";
ddoc_ext = "ddoc";
json_ext = "json";
// LDC
ll_ext = "ll";
@@ -56,7 +58,7 @@ Global::Global()
copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v1.045";
version = "v1.051";
ldc_version = LDC_REV;
llvm_version = LLVM_REV_STR;
global.structalign = 8;
@@ -90,6 +92,11 @@ Loc::Loc(Module *mod, unsigned linnum)
this->filename = mod ? mod->srcfile->toChars() : NULL;
}
bool Loc::equals(const Loc& loc)
{
return linnum == loc.linnum && FileName::equals(filename, loc.filename);
}
/**************************************
* Print error message and exit.
*/
@@ -180,25 +187,20 @@ void halt()
void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
{
char *env;
char *p;
Array *argv;
int argc;
int wildcard; // do wildcard expansion
int instring;
int slash;
char c;
int j;
env = getenv(envvar);
char *env = getenv(envvar);
if (!env)
return;
env = mem.strdup(env); // create our own writable copy
argc = *pargc;
argv = new Array();
int argc = *pargc;
Array *argv = new Array();
argv->setDim(argc);
int argc_left = 0;
@@ -220,10 +222,10 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
argv->push((char*)"");
argc++;
j = 1; // leave argv[0] alone
int j = 1; // leave argv[0] alone
while (1)
{
wildcard = 1;
int wildcard = 1; // do wildcard expansion
switch (*env)
{
case ' ':

View File

@@ -48,6 +48,7 @@ the target object file format:
TARGET_OSX Covers 32 and 64 bit Mac OSX
TARGET_FREEBSD Covers 32 and 64 bit FreeBSD
TARGET_SOLARIS Covers 32 and 64 bit Solaris
TARGET_NET Covers .Net
It is expected that the compiler for each platform will be able
to generate 32 and 64 bit code from the same compiler binary.
@@ -161,6 +162,7 @@ struct Param
bool optimize; // run optimizer
char optimizeLevel; // optimization level
#endif
char vtls; // identify thread local variables
ARCH cpu; // target CPU
OS os; // target OS
bool is64bit; // generate 64 bit code
@@ -193,6 +195,9 @@ struct Param
char *hdrdir; // write 'header' file to docdir directory
char *hdrname; // write 'header' file to docname
char doXGeneration; // write JSON file
char *xfilename; // write JSON file to xfilename
unsigned debuglevel; // debug level
Array *debugids; // debug identifiers
@@ -204,11 +209,9 @@ struct Param
Array *defaultlibnames; // default libraries for non-debug builds
Array *debuglibnames; // default libraries for debug builds
const char *xmlname; // filename for XML output
OutBuffer *moduleDeps; // buffer and filename for emitting module deps
char *moduleDepsFile;
char *moduleDepsFile; // filename for deps output
OutBuffer *moduleDeps; // contents to be written to deps file
// Hidden debug switches
bool debuga;
bool debugb;
@@ -260,6 +263,7 @@ struct Global
const char *doc_ext; // for Ddoc generated files
const char *ddoc_ext; // for Ddoc macro include files
const char *hdr_ext; // for D 'header' import files
const char *json_ext; // for JSON files
const char *copyright;
const char *written;
Array *path; // Array of char*'s which form the import lookup path
@@ -344,7 +348,7 @@ struct Module;
//typedef unsigned Loc; // file location
struct Loc
{
char *filename;
const char *filename;
unsigned linnum;
Loc()
@@ -362,6 +366,7 @@ struct Loc
Loc(Module *mod, unsigned linnum);
char *toChars() const;
bool equals(const Loc& loc);
};
#ifndef GCC_SAFE_DMD
@@ -426,7 +431,7 @@ void halt();
#if IN_GCC || IN_LLVM
#define stdmsg stderr
#else
#define stdmsg stdout
#define stdmsg stderr
#endif
#endif /* DMD_MARS_H */

View File

@@ -95,7 +95,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
searchCacheSymbol = NULL;
searchCacheFlags = 0;
semanticstarted = 0;
semanticdone = 0;
semanticRun = 0;
decldefs = NULL;
vmoduleinfo = NULL;
#if IN_DMD
@@ -123,6 +123,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
macrotable = NULL;
escapetable = NULL;
safe = FALSE;
#if IN_DMD
doppelganger = 0;
cov = NULL;
@@ -661,9 +662,65 @@ void Module::parse()
}
}
void Module::semantic(Scope* unused_sc)
{ int i;
void Module::importAll(Scope *prevsc)
{
//printf("+Module::importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
if (scope)
return; // already done
/* Note that modules get their own scope, from scratch.
* This is so regardless of where in the syntax a module
* gets imported, it is unaffected by context.
* Ignore prevsc.
*/
Scope *sc = Scope::createGlobal(this); // create root scope
// Add import of "object" if this module isn't "object"
if (ident != Id::object)
{
if (members->dim == 0 || ((Dsymbol *)members->data[0])->ident != Id::object)
{
Import *im = new Import(0, NULL, Id::object, NULL, 0);
members->shift(im);
}
}
if (!symtab)
{
// Add all symbols into module's symbol table
symtab = new DsymbolTable();
for (int i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
s->addMember(NULL, sc->scopesym, 1);
}
}
// anything else should be run after addMember, so version/debug symbols are defined
/* Set scope for the symbols so that if we forward reference
* a symbol, it can possibly be resolved on the spot.
* If this works out well, it can be extended to all modules
* before any semantic() on any of them.
*/
setScope(sc); // remember module scope for semantic
for (int i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
s->setScope(sc);
}
for (int i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
s->importAll(sc);
}
sc = sc->pop();
sc->pop(); // 2 pops because Scope::createGlobal() created 2
}
void Module::semantic(Scope *unused_sc)
{
if (semanticstarted)
return;
@@ -673,10 +730,15 @@ void Module::semantic(Scope* unused_sc)
// Note that modules get their own scope, from scratch.
// This is so regardless of where in the syntax a module
// gets imported, it is unaffected by context.
Scope *sc = Scope::createGlobal(this); // create root scope
Scope *sc = scope; // see if already got one from importAll()
if (!sc)
{ printf("test2\n");
Scope::createGlobal(this); // create root scope
}
//printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
#if 0
// Add import of "object" if this module isn't "object"
if (ident != Id::object)
{
@@ -686,26 +748,36 @@ void Module::semantic(Scope* unused_sc)
// Add all symbols into module's symbol table
symtab = new DsymbolTable();
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
for (int i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
s->addMember(NULL, sc->scopesym, 1);
}
// Pass 1 semantic routines: do public side of the definition
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
/* Set scope for the symbols so that if we forward reference
* a symbol, it can possibly be resolved on the spot.
* If this works out well, it can be extended to all modules
* before any semantic() on any of them.
*/
for (int i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
s->setScope(sc);
}
#endif
// Pass 1 semantic routines: do public side of the definition
for (int i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
s = (Dsymbol *)members->data[i];
//printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
s->semantic(sc);
runDeferredSemantic();
}
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
if (!scope)
{ sc = sc->pop();
sc->pop(); // 2 pops because Scope::createGlobal() created 2
}
semanticRun = semanticstarted;
//printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
}
@@ -744,7 +816,7 @@ void Module::semantic2(Scope* unused_sc)
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
semanticRun = semanticstarted;
//printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
}
@@ -774,12 +846,11 @@ void Module::semantic3(Scope* unused_sc)
sc = sc->pop();
sc->pop();
semanticdone = semanticstarted;
semanticRun = semanticstarted;
}
void Module::inlineScan()
{ int i;
{
if (semanticstarted >= 4)
return;
assert(semanticstarted == 3);
@@ -790,16 +861,14 @@ void Module::inlineScan()
// gets imported, it is unaffected by context.
//printf("Module = %p\n", sc.scopesym);
for (i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
for (int i = 0; i < members->dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i];
//if (global.params.verbose)
//printf("inline scan symbol %s\n", s->toChars());
s->inlineScan();
}
semanticdone = semanticstarted;
semanticRun = semanticstarted;
}
/****************************************************
@@ -844,6 +913,7 @@ Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
{
/* Since modules can be circularly referenced,
* need to stop infinite recursive searches.
* This is done with the cache.
*/
//printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
@@ -851,7 +921,10 @@ Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
if (insearch)
s = NULL;
else if (searchCacheIdent == ident && searchCacheFlags == flags)
{
s = searchCacheSymbol;
//printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", toChars(), ident->toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol->toChars() : "null");
}
else
{
insearch = 1;
@@ -865,6 +938,13 @@ Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
return s;
}
Dsymbol *Module::symtabInsert(Dsymbol *s)
{
searchCacheIdent = 0; // symbol is inserted, so invalidate cache
return Package::symtabInsert(s);
}
/*******************************************
* Can't run semantic on s now, try again later.
*/
@@ -1059,11 +1139,14 @@ DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppk
else
{
assert(p->isPackage());
#if TARGET_NET //dot net needs modules and packages with same name
#else
if (p->isModule())
{ p->error("module and package have the same name");
fatal();
break;
}
#endif
}
parent = p;
dst = ((Package *)p)->symtab;

View File

@@ -94,7 +94,7 @@ struct Module : Package
int searchCacheFlags; // cached flags
int semanticstarted; // has semantic() been started?
int semanticdone; // has semantic() been done?
int semanticRun; // has semantic() been done?
int root; // != 0 if this is a 'root' module,
// i.e. a module that will be taken all the
// way to an object file
@@ -119,8 +119,10 @@ struct Module : Package
Macro *macrotable; // document comment macros
struct Escape *escapetable; // document comment escapes
int doDocComment; // enable generating doc comments for this module
int doHdrGen; // enable generating header file for this module
int doDocComment; // enable generating doc comments for this module
int doHdrGen; // enable generating header file for this module
bool safe; // TRUE if module is marked as 'safe'
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
~Module();
@@ -128,6 +130,7 @@ struct Module : Package
static Module *load(Loc loc, Array *packages, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf);
const char *kind();
void read(Loc loc); // read file
#if IN_GCC
@@ -135,6 +138,7 @@ struct Module : Package
#else
void parse(); // syntactic parse
#endif
void importAll(Scope *sc);
void semantic(Scope* unused_sc = NULL); // semantic analysis
void semantic2(Scope* unused_sc = NULL); // pass 2 semantic analysis
void semantic3(Scope* unused_sc = NULL); // pass 3 semantic analysis
@@ -146,6 +150,7 @@ struct Module : Package
void gendocfile();
int needModuleInfo();
Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *symtabInsert(Dsymbol *s);
void deleteObjFile();
void addDeferredSemantic(Dsymbol *s);
void runDeferredSemantic();
@@ -198,6 +203,7 @@ struct ModuleDeclaration
{
Identifier *id;
Array *packages; // array of Identifier's representing packages
bool safe;
ModuleDeclaration(Array *packages, Identifier *id);

View File

@@ -1514,16 +1514,8 @@ MATCH TypeBasic::implicitConvTo(Type *to)
if (ty == Tvoid || to->ty == Tvoid)
return MATCHnomatch;
if (1 || global.params.Dversion == 1)
{
if (to->ty == Tbool)
return MATCHnomatch;
}
else
{
if (ty == Tbool || to->ty == Tbool)
return MATCHnomatch;
}
if (to->ty == Tbool)
return MATCHnomatch;
if (!to->isTypeBasic())
return MATCHnomatch;
@@ -1534,6 +1526,7 @@ MATCH TypeBasic::implicitConvTo(Type *to)
if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
return MATCHnomatch;
#if DMDV2
// If converting to integral
if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
{ d_uns64 sz = size(0);
@@ -1547,6 +1540,7 @@ MATCH TypeBasic::implicitConvTo(Type *to)
/*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
return MATCHnomatch;*/
}
#endif
}
else if (flags & TFLAGSfloating)
{
@@ -2347,6 +2341,7 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc)
case Tfunction:
case Tvoid:
case Tnone:
case Ttuple:
error(loc, "can't have associative array key of %s", key->toChars());
break;
}
@@ -2557,6 +2552,9 @@ Type *TypePointer::syntaxCopy()
Type *TypePointer::semantic(Loc loc, Scope *sc)
{
if (deco)
return this;
//printf("TypePointer::semantic()\n");
Type *n = next->semantic(loc, sc);
switch (n->toBasetype()->ty)
@@ -2792,6 +2790,9 @@ int Type::covariant(Type *t)
Type *t1n = t1->next;
Type *t2n = t2->next;
if (!t1n || !t2n) // happens with return type inference
goto Lnotcovariant;
if (t1n->equals(t2n))
goto Lcovariant;
if (t1n->ty != Tclass || t2n->ty != Tclass)
@@ -2936,10 +2937,10 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
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;
case LINKc: p = " C"; break;
case LINKwindows: p = " Windows"; break;
case LINKpascal: p = " Pascal"; break;
case LINKcpp: p = " C++"; break;
// LDC
case LINKintrinsic: p = "Intrinsic"; break;
@@ -2978,36 +2979,39 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
tf->linkage = sc->linkage;
if (!tf->next)
if (tf->next)
{
assert(global.errors);
tf->next = tvoid;
tf->next = tf->next->semantic(loc,sc);
if (tf->next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", tf->next->toChars());
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Ttuple)
{ error(loc, "functions cannot return a tuple");
tf->next = Type::terror;
}
if (tf->next->isscope() && !(sc->flags & SCOPEctor))
error(loc, "functions cannot return scope %s", tf->next->toChars());
}
tf->next = tf->next->semantic(loc,sc);
if (tf->next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", tf->next->toChars());
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
tf->next = Type::terror;
}
if (tf->next->toBasetype()->ty == Ttuple)
{ error(loc, "functions cannot return a tuple");
tf->next = Type::terror;
}
if (tf->next->isscope() && !(sc->flags & SCOPEctor))
error(loc, "functions cannot return scope %s", tf->next->toChars());
if (tf->parameters)
{ size_t dim = Argument::dim(tf->parameters);
{
/* Create a scope for evaluating the default arguments for the parameters
*/
Scope *argsc = sc->push();
argsc->stc = 0; // don't inherit storage class
argsc->protection = PROTpublic;
size_t dim = Argument::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{ Argument *arg = Argument::getNth(tf->parameters, i);
Type *t;
tf->inuse++;
arg->type = arg->type->semantic(loc,sc);
arg->type = arg->type->semantic(loc, argsc);
if (tf->inuse == 1) tf->inuse--;
// each function needs its own copy of a tuple arg, since
@@ -3019,7 +3023,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
if (tf->inuse == 1) tf->inuse--;
}
t = arg->type->toBasetype();
Type *t = arg->type->toBasetype();
if (arg->storageClass & (STCout | STCref | STClazy))
{
@@ -3031,9 +3035,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
if (arg->defaultArg)
{
arg->defaultArg = arg->defaultArg->semantic(sc);
arg->defaultArg = resolveProperties(sc, arg->defaultArg);
arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type);
arg->defaultArg = arg->defaultArg->semantic(argsc);
arg->defaultArg = resolveProperties(argsc, arg->defaultArg);
arg->defaultArg = arg->defaultArg->implicitCastTo(argsc, arg->type);
}
/* If arg turns out to be a tuple, the number of parameters may
@@ -3044,8 +3048,10 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
i--;
}
}
argsc->pop();
}
tf->deco = tf->merge()->deco;
if (tf->next)
tf->deco = tf->merge()->deco;
if (tf->inuse)
{ error(loc, "recursive type");
@@ -3419,6 +3425,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
goto Lerror;
goto L3;
}
else if (v && id == Id::stringof)
{
e = new DsymbolExp(loc, s);
do
{
id = (Identifier *)idents.data[i];
e = new DotIdExp(loc, e, id);
} while (++i < idents.dim);
e = e->semantic(sc);
*pe = e;
return;
}
t = s->getType();
if (!t && s->isDeclaration())
t = s->isDeclaration()->type;
@@ -3515,23 +3534,33 @@ L1:
{
if (t->reliesOnTident())
{
Scope *scx;
for (scx = sc; 1; scx = scx->enclosing)
if (s->scope)
t = t->semantic(loc, s->scope);
else
{
if (!scx)
{ error(loc, "forward reference to '%s'", t->toChars());
return;
/* Attempt to find correct scope in which to evaluate t.
* Not sure if this is right or not, or if we should just
* give forward reference error if s->scope is not set.
*/
for (Scope *scx = sc; 1; scx = scx->enclosing)
{
if (!scx)
{ error(loc, "forward reference to '%s'", t->toChars());
return;
}
if (scx->scopesym == scopesym)
{
t = t->semantic(loc, scx);
break;
}
}
if (scx->scopesym == scopesym)
break;
}
t = t->semantic(loc, scx);
//((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps);
}
}
if (t->ty == Ttuple)
*pt = t;
else if (t->ty == Ttypeof)
*pt = t->semantic(loc, sc);
else
*pt = t->merge();
}
@@ -3762,7 +3791,8 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc)
if (!t)
{
#ifdef DEBUG
printf("2: ");
if (s) printf("s = %s\n", s->kind());
printf("2: e:%p s:%p ", e, s);
#endif
error(loc, "%s is used as a type", toChars());
t = tvoid;
@@ -3839,6 +3869,11 @@ void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
toCBuffer2Helper(buf, hgs);
}
void TypeTypeof::toDecoBuffer(OutBuffer *buf, bool mangle)
{
assert(0);
}
Type *TypeTypeof::semantic(Loc loc, Scope *sc)
{ Expression *e;
Type *t;
@@ -3970,7 +4005,7 @@ Type *TypeEnum::syntaxCopy()
Type *TypeEnum::semantic(Loc loc, Scope *sc)
{
sym->semantic(sc);
//sym->semantic(sc);
return merge();
}
@@ -4562,7 +4597,7 @@ L1:
TemplateInstance *ti = s->isTemplateInstance();
if (ti)
{ if (!ti->semanticdone)
{ if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
if (!s->isTemplateInstance())
@@ -4695,7 +4730,7 @@ TypeClass::TypeClass(ClassDeclaration *sym)
char *TypeClass::toChars()
{
return sym->toPrettyChars();
return (char *)sym->toPrettyChars();
}
Type *TypeClass::syntaxCopy()
@@ -4706,8 +4741,8 @@ Type *TypeClass::syntaxCopy()
Type *TypeClass::semantic(Loc loc, Scope *sc)
{
//printf("TypeClass::semantic(%s)\n", sym->toChars());
if (sym->scope)
sym->semantic(sym->scope);
if (deco)
return this;
return merge();
}
@@ -4975,7 +5010,7 @@ L1:
TemplateInstance *ti = s->isTemplateInstance();
if (ti)
{ if (!ti->semanticdone)
{ if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
if (!s->isTemplateInstance())
@@ -4994,9 +5029,16 @@ L1:
if (e->op == TOKtype)
{
VarExp *ve;
if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
/* It's:
* Class.d
*/
if (d->isTupleDeclaration())
{
e = new TupleExp(e->loc, d->isTupleDeclaration());
e = e->semantic(sc);
return e;
}
else if (d->needThis() && (hasThis(sc) || !(sc->intypeof || d->isFuncDeclaration())))
{
if (sc->func)
{
@@ -5025,15 +5067,11 @@ L1:
e = de->semantic(sc);
return e;
}
else if (d->isTupleDeclaration())
{
e = new TupleExp(e->loc, d->isTupleDeclaration());
e = e->semantic(sc);
return e;
}
else
ve = new VarExp(e->loc, d);
return ve;
{
VarExp *ve = new VarExp(e->loc, d);
return ve;
}
}
if (d->isDataseg())

View File

@@ -561,6 +561,7 @@ struct TypeTypeof : TypeQualified
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toDecoBuffer(OutBuffer *buf, bool mangle);
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
};

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -33,7 +33,7 @@
static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id);
static void inferApplyArgTypesX(Module* from, FuncDeclaration *fstart, Arguments *arguments);
static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments);
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments);
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
/******************************** Expression **************************/
@@ -158,6 +158,7 @@ Identifier *ArrayExp::opId() { return Id::index; }
Expression *UnaExp::op_overload(Scope *sc)
{
//printf("UnaExp::op_overload() (%s)\n", toChars());
AggregateDeclaration *ad;
Dsymbol *fd;
Type *t1 = e1->type->toBasetype();
@@ -177,10 +178,11 @@ Expression *UnaExp::op_overload(Scope *sc)
{
if (op == TOKarray)
{
Expression *e;
/* Rewrite op e1[arguments] as:
* e1.fd(arguments)
*/
Expression *e = new DotIdExp(loc, e1, fd->ident);
ArrayExp *ae = (ArrayExp *)this;
e = new DotIdExp(loc, e1, fd->ident);
e = new CallExp(loc, e, ae->arguments);
e = e->semantic(sc);
return e;
@@ -191,6 +193,21 @@ Expression *UnaExp::op_overload(Scope *sc)
return build_overload(loc, sc, e1, NULL, fd->ident);
}
}
#if DMDV2
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
{
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
return e;
}
#endif
}
return NULL;
}
@@ -264,11 +281,11 @@ Expression *BinExp::op_overload(Scope *sc)
fd = s->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args2, sc->module);
overloadResolveX(&m, fd, NULL, &args2, sc->module);
}
else
{ td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args2);
templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
}
}
@@ -279,11 +296,11 @@ Expression *BinExp::op_overload(Scope *sc)
fd = s_r->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args1, sc->module);
overloadResolveX(&m, fd, NULL, &args1, sc->module);
}
else
{ td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args1);
templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
}
}
@@ -335,7 +352,6 @@ Expression *BinExp::op_overload(Scope *sc)
* b.opfunc(a)
* and see which is better.
*/
Expression *e;
FuncDeclaration *lastf;
if (!argsset)
@@ -353,11 +369,11 @@ Expression *BinExp::op_overload(Scope *sc)
fd = s_r->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args2, sc->module);
overloadResolveX(&m, fd, NULL, &args2, sc->module);
}
else
{ td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args2);
templateResolve(&m, td, sc, loc, NULL, NULL, &args2);
}
}
lastf = m.lastf;
@@ -367,11 +383,11 @@ Expression *BinExp::op_overload(Scope *sc)
fd = s->isFuncDeclaration();
if (fd)
{
overloadResolveX(&m, fd, &args1, sc->module);
overloadResolveX(&m, fd, NULL, &args1, sc->module);
}
else
{ td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, NULL, &args1);
templateResolve(&m, td, sc, loc, NULL, NULL, &args1);
}
}
@@ -388,6 +404,7 @@ Expression *BinExp::op_overload(Scope *sc)
m.lastf = m.anyf;
}
Expression *e;
if (lastf && m.lastf == lastf ||
id_r && m.last == MATCHnomatch)
// Rewrite (e1 op e2) as e1.opfunc_r(e2)
@@ -423,6 +440,33 @@ Expression *BinExp::op_overload(Scope *sc)
}
}
#if DMDV2
// Try alias this on first operand
if (ad1 && ad1->aliasthis)
{
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->semantic(sc);
return e;
}
// Try alias this on second operand
if (ad2 && ad2->aliasthis)
{
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->semantic(sc);
return e;
}
#endif
return NULL;
}
@@ -430,7 +474,7 @@ Expression *BinExp::op_overload(Scope *sc)
* Utility to build a function call out of this reference and argument.
*/
static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id)
{
Expression *e;
@@ -499,7 +543,6 @@ void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr, Mod
}
AggregateDeclaration *ad;
FuncDeclaration *fd;
Argument *arg = (Argument *)arguments->data[0];
Type *taggr = aggr->type;
@@ -570,7 +613,7 @@ void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr, Mod
: Id::apply);
if (s)
{
fd = s->isFuncDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
if (fd)
inferApplyArgTypesX(from, fd, arguments);
}
@@ -582,7 +625,7 @@ void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr, Mod
if (0 && aggr->op == TOKdelegate)
{ DelegateExp *de = (DelegateExp *)aggr;
fd = de->func->isFuncDeclaration();
FuncDeclaration *fd = de->func->isFuncDeclaration();
if (fd)
inferApplyArgTypesX(from, fd, arguments);
}
@@ -719,7 +762,7 @@ static int inferApplyArgTypesY(TypeFunction *tf, Arguments *arguments)
/**************************************
*/
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments)
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
{
FuncDeclaration *fd;

File diff suppressed because it is too large Load Diff

10677
dmd/parse.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,177 +1,182 @@
#define _MT 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#include <stdio.h>
#include <errno.h>
#include <process.h>
#include "root.h"
#include "rmem.h"
static unsigned __stdcall startthread(void *p);
struct FileData
{
File *file;
int result;
HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL,
0,
&startthread,
this,
0,
(unsigned *)&threadaddr);
if (hThread)
{
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
else
{
assert(0);
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
WaitForSingleObject(f->event, INFINITE);
Sleep(0); // give up time slice
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
}
unsigned __stdcall startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
for (size_t i = 0; i < aw->filesdim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
SetEvent(f->event);
}
_endthreadex(EXIT_SUCCESS);
return EXIT_SUCCESS; // if skidding
}
#else
#include <stdio.h>
#include <errno.h>
#include "root.h"
#include "rmem.h"
struct FileData
{
File *file;
int result;
//HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
//HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
//ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
f->result = f->file->read();
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
}
#endif
#define _MT 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if _WIN32
#include <windows.h>
#include <stdio.h>
#include <errno.h>
#include <process.h>
#include "root.h"
#include "rmem.h"
static unsigned __stdcall startthread(void *p);
struct FileData
{
File *file;
int result;
HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
//printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim)
{
unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL,
0,
&startthread,
this,
0,
(unsigned *)&threadaddr);
if (hThread)
{
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
else
{
assert(0);
}
}
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
WaitForSingleObject(f->event, INFINITE);
Sleep(0); // give up time slice
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
}
unsigned __stdcall startthread(void *p)
{
AsyncRead *aw = (AsyncRead *)p;
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
for (size_t i = 0; i < aw->filesdim; i++)
{ FileData *f = &aw->files[i];
f->result = f->file->read();
SetEvent(f->event);
}
_endthreadex(EXIT_SUCCESS);
return EXIT_SUCCESS; // if skidding
}
#else
#include <stdio.h>
#include <errno.h>
#include "root.h"
#include "rmem.h"
struct FileData
{
File *file;
int result;
//HANDLE event;
};
struct AsyncRead
{
static AsyncRead *create(size_t nfiles);
void addFile(File *file);
void start();
int read(size_t i);
static void dispose(AsyncRead *);
//HANDLE hThread;
size_t filesdim;
size_t filesmax;
FileData files[1];
};
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
}
void AsyncRead::addFile(File *file)
{
//printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax);
files[filesdim].file = file;
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
//ResetEvent(files[filesdim].event);
filesdim++;
}
void AsyncRead::start()
{
}
int AsyncRead::read(size_t i)
{
FileData *f = &files[i];
f->result = f->file->read();
return f->result;
}
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
}
#endif

View File

@@ -37,7 +37,7 @@ void browse(const char *url)
pid_t childpid;
const char *args[3];
char *browser = getenv("BROWSER");
const char *browser = getenv("BROWSER");
if (browser)
browser = strdup(browser);
else

View File

@@ -415,10 +415,12 @@ Array *FileName::splitPath(const char *path)
continue;
#endif
#if 0
case ' ':
case '\t': // tabs in filenames?
if (!instring) // if not in string
break; // treat as end of path
#endif
default:
Ldefault:
buf.writeByte(c);

View File

@@ -71,6 +71,7 @@ Scope::Scope()
this->nofree = 0;
this->noctor = 0;
this->noaccesscheck = 0;
this->mustsemantic = 0;
this->intypeof = 0;
this->parameterSpecialization = 0;
this->callSuper = 0;
@@ -119,6 +120,7 @@ Scope::Scope(Scope *enclosing)
this->nofree = 0;
this->noctor = enclosing->noctor;
this->noaccesscheck = enclosing->noaccesscheck;
this->mustsemantic = enclosing->mustsemantic;
this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper;
@@ -282,7 +284,7 @@ Dsymbol *Scope::insert(Dsymbol *s)
//printf("\t\tsc->scopesym = %p\n", sc->scopesym);
if (!sc->scopesym->symtab)
sc->scopesym->symtab = new DsymbolTable();
return sc->scopesym->symtab->insert(s);
return sc->scopesym->symtabInsert(s);
}
}
assert(0);

View File

@@ -1,125 +1,126 @@
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_SCOPE_H
#define DMD_SCOPE_H
#ifdef __DMC__
#pragma once
#endif
struct Dsymbol;
struct ScopeDsymbol;
struct Array;
struct Identifier;
struct Module;
struct Statement;
struct SwitchStatement;
struct TryFinallyStatement;
struct LabelStatement;
struct ForeachStatement;
struct ClassDeclaration;
struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
struct TemplateInstance;
#if IN_LLVM
struct EnclosingHandler;
struct AnonDeclaration;
#endif
#if __GNUC__
// Requires a full definition for PROT and LINK
#include "dsymbol.h" // PROT
#include "mars.h" // LINK
#else
enum LINK;
enum PROT;
#endif
struct Scope
{
Scope *enclosing; // enclosing Scope
Module *module; // Root module
ScopeDsymbol *scopesym; // current symbol
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
// sd gets the addMember()
FuncDeclaration *func; // function we are in
Dsymbol *parent; // parent to use
LabelStatement *slabel; // enclosing labelled statement
SwitchStatement *sw; // enclosing switch statement
TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block
TemplateInstance *tinst; // enclosing template instance
Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
Statement *sbreak; // enclosing statement that supports "break"
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
unsigned offset; // next offset to use in aggregate
int inunion; // we're processing members of a union
int incontract; // we're inside contract code
int nofree; // set if shouldn't free it
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()
#define CSXsuper_ctor 2 // called super()
#define CSXthis 4 // referenced this
#define CSXsuper 8 // referenced super
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
unsigned structalign; // alignment for struct members
enum LINK linkage; // linkage for external functions
enum PROT protection; // protection for class members
int explicitProtection; // set if in an explicit protection attribute
unsigned stc; // storage class
unsigned flags;
#define SCOPEctor 1 // constructor type
#define SCOPEstaticif 2 // inside static if
#define SCOPEfree 4 // is on free list
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
OutBuffer *docbuf; // buffer for documentation output
static Scope *freelist;
static void *operator new(size_t sz);
static Scope *createGlobal(Module *module);
Scope();
Scope(Module *module);
Scope(Scope *enclosing);
Scope *push();
Scope *push(ScopeDsymbol *ss);
Scope *pop();
void mergeCallSuper(Loc loc, unsigned cs);
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
Dsymbol *insert(Dsymbol *s);
ClassDeclaration *getClassScope();
AggregateDeclaration *getStructClassScope();
void setNoFree();
};
#endif /* DMD_SCOPE_H */
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef DMD_SCOPE_H
#define DMD_SCOPE_H
#ifdef __DMC__
#pragma once
#endif
struct Dsymbol;
struct ScopeDsymbol;
struct Array;
struct Identifier;
struct Module;
struct Statement;
struct SwitchStatement;
struct TryFinallyStatement;
struct LabelStatement;
struct ForeachStatement;
struct ClassDeclaration;
struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
struct TemplateInstance;
#if IN_LLVM
struct EnclosingHandler;
struct AnonDeclaration;
#endif
#if __GNUC__
// Requires a full definition for PROT and LINK
#include "dsymbol.h" // PROT
#include "mars.h" // LINK
#else
enum LINK;
enum PROT;
#endif
struct Scope
{
Scope *enclosing; // enclosing Scope
Module *module; // Root module
ScopeDsymbol *scopesym; // current symbol
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
// sd gets the addMember()
FuncDeclaration *func; // function we are in
Dsymbol *parent; // parent to use
LabelStatement *slabel; // enclosing labelled statement
SwitchStatement *sw; // enclosing switch statement
TryFinallyStatement *enclosingFinally; // enclosing try finally statement; set inside its finally block
TemplateInstance *tinst; // enclosing template instance
Statement *enclosingScopeExit; // enclosing statement that wants to do something on scope exit
Statement *sbreak; // enclosing statement that supports "break"
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
unsigned offset; // next offset to use in aggregate
int inunion; // we're processing members of a union
int incontract; // we're inside contract code
int nofree; // set if shouldn't free it
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
int mustsemantic; // cannot defer semantic()
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()
#define CSXsuper_ctor 2 // called super()
#define CSXthis 4 // referenced this
#define CSXsuper 8 // referenced super
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
unsigned structalign; // alignment for struct members
enum LINK linkage; // linkage for external functions
enum PROT protection; // protection for class members
int explicitProtection; // set if in an explicit protection attribute
unsigned stc; // storage class
unsigned flags;
#define SCOPEctor 1 // constructor type
#define SCOPEstaticif 2 // inside static if
#define SCOPEfree 4 // is on free list
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
OutBuffer *docbuf; // buffer for documentation output
static Scope *freelist;
static void *operator new(size_t sz);
static Scope *createGlobal(Module *module);
Scope();
Scope(Module *module);
Scope(Scope *enclosing);
Scope *push();
Scope *push(ScopeDsymbol *ss);
Scope *pop();
void mergeCallSuper(Loc loc, unsigned cs);
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
Dsymbol *insert(Dsymbol *s);
ClassDeclaration *getClassScope();
AggregateDeclaration *getStructClassScope();
void setNoFree();
};
#endif /* DMD_SCOPE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -310,7 +310,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->members = decldefs;
this->overnext = NULL;
this->overroot = NULL;
this->scope = NULL;
this->semanticRun = 0;
this->onemember = NULL;
}
@@ -350,8 +350,9 @@ void TemplateDeclaration::semantic(Scope *sc)
#if LOG
printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars());
#endif
if (scope)
if (semanticRun)
return; // semantic() already run
semanticRun = 1;
if (sc->func)
{
@@ -803,16 +804,19 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
{ // Set initial template arguments
nargsi = targsi->dim;
if (nargsi > parameters->dim)
size_t n = parameters->dim;
if (nargsi > n)
{ if (!tp)
goto Lnomatch;
dedargs->setDim(nargsi);
dedargs->zero();
}
else
n = nargsi;
memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
memcpy(dedargs->data, targsi->data, n * sizeof(*dedargs->data));
for (size_t i = 0; i < nargsi; i++)
for (size_t i = 0; i < n; i++)
{ assert(i < parameters->dim);
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
MATCH m;
@@ -844,7 +848,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
fdtype = (TypeFunction *)fd->type;
nfparams = Argument::dim(fdtype->parameters); // number of function parameters
nfargs = fargs->dim; // number of function arguments
nfargs = fargs ? fargs->dim : 0; // number of function arguments
/* Check for match of function arguments with variadic template
* parameter, such as:
@@ -854,7 +858,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
*/
if (tp) // if variadic
{
if (nfparams == 0) // if no function parameters
if (nfparams == 0 && nfargs != 0) // if no function parameters
{
Tuple *t = new Tuple();
//printf("t = %p\n", t);
@@ -1293,7 +1297,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
for (TemplateDeclaration *td = this; td; td = td->overnext)
{
if (!td->scope)
if (!td->semanticRun)
{
error("forward reference to template %s", td->toChars());
goto Lerror;
@@ -1901,14 +1905,21 @@ MATCH TypeInstance::deduceType(Scope *sc,
L2:
for (int i = 0; i < tempinst->tiargs->dim; i++)
for (int i = 0; 1; i++)
{
//printf("\ttest: tempinst->tiargs[%d]\n", i);
Object *o1;
if (i < tempinst->tiargs->dim)
o1 = (Object *)tempinst->tiargs->data[i];
else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim)
// Pick up default arg
o1 = (Object *)tempinst->tdtypes.data[i];
else
break;
if (i >= tp->tempinst->tiargs->dim)
goto Lnomatch;
int j;
Object *o1 = (Object *)tempinst->tiargs->data[i];
Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
Type *t1 = isType(o1);
@@ -1934,6 +1945,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
#endif
TemplateTupleParameter *ttp;
int j;
if (t2 &&
t2->ty == Tident &&
i == tp->tempinst->tiargs->dim - 1 &&
@@ -3062,7 +3074,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticdone = 0;
this->semanticRun = 0;
this->semantictiargsdone = 0;
this->withsym = NULL;
this->nest = 0;
@@ -3096,7 +3108,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticdone = 0;
this->semanticRun = 0;
this->semantictiargsdone = 1;
this->withsym = NULL;
this->nest = 0;
@@ -3179,13 +3191,13 @@ void TemplateInstance::semantic(Scope *sc)
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
if (semanticdone != 0)
if (semanticRun != 0)
{
error(loc, "recursive template expansion");
// inst = this;
return;
}
semanticdone = 1;
semanticRun = 1;
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
@@ -3323,7 +3335,7 @@ void TemplateInstance::semantic(Scope *sc)
{ Module *m = sc->module->importedFrom;
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
a = m->members;
if (m->semanticdone >= 3)
if (m->semanticRun >= 3)
dosemantic3 = 1;
}
for (int i = 0; 1; i++)
@@ -3344,9 +3356,9 @@ void TemplateInstance::semantic(Scope *sc)
// Create our own scope for the template parameters
Scope *scope = tempdecl->scope;
if (!scope)
if (!tempdecl->semanticRun)
{
error("forward reference to template declaration %s\n", tempdecl->toChars());
error("template instantiation %s forward references template declaration %s\n", toChars(), tempdecl->toChars());
return;
}
@@ -3559,6 +3571,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
}
else if (ta)
{
Ltype:
if (ta->ty == Ttuple)
{ // Expand tuple
TypeTuple *tt = (TypeTuple *)ta;
@@ -3593,7 +3606,21 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
ea = ea->optimize(WANTvalue | WANTinterpret);
tiargs->data[j] = ea;
if (ea->op == TOKtype)
tiargs->data[j] = ea->type;
{ ta = ea->type;
goto Ltype;
}
if (ea->op == TOKtuple)
{ // Expand tuple
TupleExp *te = (TupleExp *)ea;
size_t dim = te->exps->dim;
tiargs->remove(j);
if (dim)
{ tiargs->reserve(dim);
for (size_t i = 0; i < dim; i++)
tiargs->insert(j + i, te->exps->data[i]);
}
j--;
}
}
else if (sa)
{
@@ -3736,6 +3763,23 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
#if LOG
printf("TemplateInstance::findBestMatch()\n");
#endif
// First look for forward references
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{
if (!td->semanticRun)
{
if (td->scope)
{ // Try to fix forward reference
td->semantic(td->scope);
}
if (!td->semanticRun)
{
error("%s forward references template declaration %s\n", toChars(), td->toChars());
return NULL;
}
}
}
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{
MATCH m;
@@ -3752,11 +3796,7 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
dedtypes.setDim(td->parameters->dim);
dedtypes.zero();
if (!td->scope)
{
error("forward reference to template declaration %s", td->toChars());
return NULL;
}
assert(td->semanticRun);
m = td->matchWithInstance(this, &dedtypes, 0);
//printf("matchWithInstance = %d\n", m);
if (!m) // no match at all
@@ -3964,6 +4004,7 @@ Identifier *TemplateInstance::genIdent()
{ sinteger_t v;
real_t r;
ea = ea->optimize(WANTvalue | WANTinterpret);
if (ea->op == TOKvar)
{
sa = ((VarExp *)ea)->var;
@@ -4030,7 +4071,7 @@ Identifier *TemplateInstance::genIdent()
* template instance arguments.
*/
void TemplateInstance::declareParameters(Scope *scope)
void TemplateInstance::declareParameters(Scope *sc)
{
//printf("TemplateInstance::declareParameters()\n");
for (int i = 0; i < tdtypes.dim; i++)
@@ -4040,7 +4081,7 @@ void TemplateInstance::declareParameters(Scope *scope)
Object *o = (Object *)tdtypes.data[i]; // initializer for tp
//printf("\ttdtypes[%d] = %p\n", i, o);
tempdecl->declareParameter(scope, tp, o);
tempdecl->declareParameter(sc, tp, o);
}
}
@@ -4048,9 +4089,9 @@ void TemplateInstance::declareParameters(Scope *scope)
void TemplateInstance::semantic2(Scope *sc)
{ int i;
if (semanticdone >= 2)
if (semanticRun >= 2)
return;
semanticdone = 2;
semanticRun = 2;
#if LOG
printf("+TemplateInstance::semantic2('%s')\n", toChars());
#endif
@@ -4080,12 +4121,12 @@ printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
void TemplateInstance::semantic3(Scope *sc)
{
#if LOG
printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone);
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
#endif
//if (toChars()[0] == 'D') *(char*)0=0;
if (semanticdone >= 3)
if (semanticRun >= 3)
return;
semanticdone = 3;
semanticRun = 3;
if (!errors && members)
{
sc = tempdecl->scope;
@@ -4182,6 +4223,7 @@ Dsymbol *TemplateInstance::toAlias()
#endif
if (!inst)
{ error("cannot resolve forward reference");
errors = 1;
return this;
}
@@ -4274,7 +4316,6 @@ TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
this->tqual = tqual;
this->idents = idents;
this->tiargs = tiargs ? tiargs : new Objects();
this->scope = NULL;
}
Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
@@ -4308,18 +4349,22 @@ void TemplateMixin::semantic(Scope *sc)
printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
fflush(stdout);
#endif
if (semanticdone &&
if (semanticRun)
{
// This for when a class/struct contains mixin members, and
// is done over because of forward references
(!parent || !toParent()->isAggregateDeclaration()))
{
if (parent && toParent()->isAggregateDeclaration())
semanticRun = 1; // do over
else
{
#if LOG
printf("\tsemantic done\n");
printf("\tsemantic done\n");
#endif
return;
return;
}
}
if (!semanticdone)
semanticdone = 1;
if (!semanticRun)
semanticRun = 1;
#if LOG
printf("\tdo semantic\n");
#endif
@@ -4394,7 +4439,7 @@ void TemplateMixin::semantic(Scope *sc)
assert(tempdecl);
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{
if (!td->scope)
if (!td->semanticRun)
{
/* Cannot handle forward references if mixin is a struct member,
* because addField must happen during struct's semantic, not
@@ -4402,7 +4447,7 @@ void TemplateMixin::semantic(Scope *sc)
* runDeferred will re-run mixin's semantic outside of the struct's
* semantic.
*/
semanticdone = 0;
semanticRun = 0;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad)
ad->sizeok = 2;
@@ -4420,6 +4465,8 @@ void TemplateMixin::semantic(Scope *sc)
// Run semantic on each argument, place results in tiargs[]
semanticTiargs(sc);
if (errors)
return;
tempdecl = findBestMatch(sc);
if (!tempdecl)
@@ -4508,19 +4555,19 @@ void TemplateMixin::semantic(Scope *sc)
argsym = new ScopeDsymbol();
argsym->parent = scy->parent;
Scope *scope = scy->push(argsym);
Scope *argscope = scy->push(argsym);
unsigned errorsave = global.errors;
// Declare each template parameter as an alias for the argument type
declareParameters(scope);
declareParameters(argscope);
// Add members to enclosing scope, as well as this scope
for (unsigned i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
s->addMember(scope, this, i);
s->addMember(argscope, this, i);
//sc->insert(s);
//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
//printf("s->parent = %s\n", s->parent->toChars());
@@ -4531,7 +4578,7 @@ void TemplateMixin::semantic(Scope *sc)
printf("\tdo semantic() on template instance members '%s'\n", toChars());
#endif
Scope *sc2;
sc2 = scope->push(this);
sc2 = argscope->push(this);
sc2->offset = sc->offset;
static int nest;
@@ -4574,7 +4621,7 @@ void TemplateMixin::semantic(Scope *sc)
sc2->pop();
scope->pop();
argscope->pop();
// if (!isAnonymous())
{
@@ -4588,9 +4635,9 @@ void TemplateMixin::semantic(Scope *sc)
void TemplateMixin::semantic2(Scope *sc)
{ int i;
if (semanticdone >= 2)
if (semanticRun >= 2)
return;
semanticdone = 2;
semanticRun = 2;
#if LOG
printf("+TemplateMixin::semantic2('%s')\n", toChars());
#endif
@@ -4618,9 +4665,9 @@ void TemplateMixin::semantic2(Scope *sc)
void TemplateMixin::semantic3(Scope *sc)
{ int i;
if (semanticdone >= 3)
if (semanticRun >= 3)
return;
semanticdone = 3;
semanticRun = 3;
#if LOG
printf("TemplateMixin::semantic3('%s')\n", toChars());
#endif

View File

@@ -60,7 +60,8 @@ struct TemplateDeclaration : ScopeDsymbol
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
TemplateDeclaration *overroot; // first in overnext list
Scope *scope;
int semanticRun; // 1 semantic() run
Dsymbol *onemember; // if !=NULL then one member of this template
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
@@ -73,6 +74,7 @@ struct TemplateDeclaration : ScopeDsymbol
char *toChars();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
// void toDocBuffer(OutBuffer *buf);
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
@@ -282,7 +284,7 @@ struct TemplateInstance : ScopeDsymbol
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member
WithScopeSymbol *withsym; // if a member of a with statement
int semanticdone; // has semantic() been done?
int semanticRun; // has semantic() been done?
int semantictiargsdone; // has semanticTiargs() been done?
int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
@@ -341,8 +343,6 @@ struct TemplateMixin : TemplateInstance
Array *idents;
Type *tqual;
Scope *scope; // for forward referencing
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);

View File

@@ -732,11 +732,7 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
// class name
// code from dmd
#if DMDV2
const char *name = cd->ident->toChars();
#else
char *name = cd->ident->toChars();
#endif
size_t namelen = strlen(name);
if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
{

View File

@@ -806,6 +806,17 @@ LDC_TARGETS
fatal();
#endif
// load all unconditional imports for better symbol resolving
for (int i = 0; i < modules.dim; i++)
{
m = (Module *)modules.data[i];
if (global.params.verbose)
printf("importall %s\n", m->toChars());
m->importAll(0);
}
if (global.errors)
fatal();
// Do semantic analysis
for (int i = 0; i < modules.dim; i++)
{