mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merge DMD 1.051
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
350
dmd/attrib.c
350
dmd/attrib.c
@@ -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);
|
||||
|
||||
385
dmd/attrib.h
385
dmd/attrib.h
@@ -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 */
|
||||
|
||||
52
dmd/cast.c
52
dmd/cast.c
@@ -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());
|
||||
|
||||
116
dmd/class.c
116
dmd/class.c
@@ -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
|
||||
|
||||
/*******************************************
|
||||
*/
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
3069
dmd/declaration.c
3069
dmd/declaration.c
File diff suppressed because it is too large
Load Diff
1955
dmd/declaration.h
1955
dmd/declaration.h
File diff suppressed because it is too large
Load Diff
186
dmd/doc.c
186
dmd/doc.c
@@ -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(¯otable, (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;
|
||||
}
|
||||
|
||||
191
dmd/dsymbol.c
191
dmd/dsymbol.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
189
dmd/enum.h
189
dmd/enum.h
@@ -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 */
|
||||
|
||||
476
dmd/expression.c
476
dmd/expression.c
@@ -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;
|
||||
|
||||
|
||||
@@ -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
6532
dmd/func.c
File diff suppressed because it is too large
Load Diff
@@ -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" },
|
||||
|
||||
167
dmd/import.c
167
dmd/import.c
@@ -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)
|
||||
|
||||
135
dmd/import.h
135
dmd/import.h
@@ -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 */
|
||||
|
||||
110
dmd/init.c
110
dmd/init.c
@@ -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)
|
||||
|
||||
3022
dmd/inline.c
3022
dmd/inline.c
File diff suppressed because it is too large
Load Diff
726
dmd/interpret.c
726
dmd/interpret.c
File diff suppressed because it is too large
Load Diff
@@ -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";
|
||||
|
||||
612
dmd/lexer.h
612
dmd/lexer.h
@@ -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 */
|
||||
|
||||
589
dmd/mangle.c
589
dmd/mangle.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
24
dmd/mars.c
24
dmd/mars.c
@@ -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 ' ':
|
||||
|
||||
19
dmd/mars.h
19
dmd/mars.h
@@ -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 */
|
||||
|
||||
131
dmd/module.c
131
dmd/module.c
@@ -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;
|
||||
|
||||
12
dmd/module.h
12
dmd/module.h
@@ -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);
|
||||
|
||||
|
||||
174
dmd/mtype.c
174
dmd/mtype.c
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
81
dmd/opover.c
81
dmd/opover.c
@@ -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;
|
||||
|
||||
|
||||
1627
dmd/optimize.c
1627
dmd/optimize.c
File diff suppressed because it is too large
Load Diff
10677
dmd/parse.c
10677
dmd/parse.c
File diff suppressed because it is too large
Load Diff
359
dmd/root/async.c
359
dmd/root/async.c
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
251
dmd/scope.h
251
dmd/scope.h
@@ -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 */
|
||||
|
||||
721
dmd/statement.c
721
dmd/statement.c
File diff suppressed because it is too large
Load Diff
1808
dmd/statement.h
1808
dmd/statement.h
File diff suppressed because it is too large
Load Diff
1040
dmd/struct.c
1040
dmd/struct.c
File diff suppressed because it is too large
Load Diff
147
dmd/template.c
147
dmd/template.c
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
11
gen/main.cpp
11
gen/main.cpp
@@ -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++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user