First import of dmd-2.065-b1 (7088593).

The CPP mangling is not integrated yet.
This commit is contained in:
Kai Nacke
2013-12-06 16:59:41 +01:00
parent 2fa997e6ad
commit 1de68a45b8
78 changed files with 3480 additions and 4561 deletions
-28
View File
@@ -57,7 +57,6 @@ public:
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
bool isdeprecated; // !=0 if deprecated
#if DMDV2
Dsymbol *enclosing; /* !=NULL if is nested
* pointing to the dsymbol that directly enclosing it.
* 1. The function that enclosing it (nested struct and class)
@@ -66,20 +65,17 @@ public:
* See AggregateDeclaraton::makeNested for the details.
*/
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
#endif
// Special member functions
FuncDeclarations invs; // Array of invariants
FuncDeclaration *inv; // invariant
NewDeclaration *aggNew; // allocator
DeleteDeclaration *aggDelete; // deallocator
#if DMDV2
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
CtorDeclaration *defaultCtor; // default constructor - should have no arguments, because
// it would be stored in TypeInfo_Class.defaultConstructor
Dsymbol *aliasthis; // forward unresolved lookups to aliasthis
bool noDefaultCtor; // no default construction
#endif
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *dtor; // aggregate destructor
@@ -152,7 +148,6 @@ class StructDeclaration : public AggregateDeclaration
{
public:
int zeroInit; // !=0 if initialize with 0 fill
#if DMDV2
int hasIdentityAssign; // !=0 if has identity opAssign
int hasIdentityEquals; // !=0 if has identity opEquals
FuncDeclaration *cpctor; // generated copy-constructor, if any
@@ -165,7 +160,6 @@ public:
static FuncDeclaration *xerrcmp; // object.xopCmp
structalign_t alignment; // alignment applied outside of the struct
#endif
// For 64 bit Efl function call/return ABI
Type *arg1type;
@@ -180,10 +174,6 @@ public:
const char *kind();
void finalizeSize(Scope *sc);
bool isPOD();
#if DMDV1
Expression *cloneMembers();
#endif
#if DMDV2
int needOpAssign();
int needOpEquals();
FuncDeclaration *buildOpAssign(Scope *sc);
@@ -192,7 +182,6 @@ public:
FuncDeclaration *buildOpEquals(Scope *sc);
FuncDeclaration *buildXopEquals(Scope *sc);
FuncDeclaration *buildXopCmp(Scope *sc);
#endif
void toDocBuffer(OutBuffer *buf, Scope *sc);
PROT getAccess(Dsymbol *smember); // determine access to smember
@@ -241,13 +230,8 @@ struct BaseClass
void copyBaseInterfaces(BaseClasses *);
};
#if DMDV2
#define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
#else
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size
#endif
struct ClassFlags
{
@@ -274,10 +258,6 @@ public:
static ClassDeclaration *errorException;
ClassDeclaration *baseClass; // NULL only if this is Object
#if DMDV1
CtorDeclaration *ctor;
CtorDeclaration *defaultCtor; // default constructor
#endif
FuncDeclaration *staticCtor;
FuncDeclaration *staticDtor;
Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[]
@@ -296,9 +276,7 @@ public:
TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
int com; // !=0 if this is a COM class (meaning
// it derives from IUnknown)
#if DMDV2
int cpp; // !=0 if this is a C++ interface
#endif
int isscope; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
int inuse; // to prevent recursive attempts
@@ -318,17 +296,13 @@ public:
virtual int isBaseInfoComplete();
Dsymbol *search(Loc, Identifier *ident, int flags);
ClassDeclaration *searchBase(Loc, Identifier *ident);
#if DMDV2
int isFuncHidden(FuncDeclaration *fd);
#endif
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc);
int isCOMclass();
virtual int isCOMinterface();
#if DMDV2
int isCPPclass();
virtual int isCPPinterface();
#endif
bool isAbstract();
virtual int vtblOffset();
const char *kind();
@@ -370,9 +344,7 @@ public:
const char *kind();
int isBaseInfoComplete();
int vtblOffset();
#if DMDV2
int isCPPinterface();
#endif
virtual int isCOMinterface();
#if IN_DMD
+33 -38
View File
@@ -20,40 +20,30 @@
#include "mtype.h"
#include "declaration.h"
#if DMDV2
Expression *resolveAliasThis(Scope *sc, Expression *e)
{
Type *t = e->type->toBasetype();
AggregateDeclaration *ad;
AggregateDeclaration *ad = isAggregate(t);
if (t->ty == Tclass)
{ ad = ((TypeClass *)t)->sym;
goto L1;
}
else if (t->ty == Tstruct)
{ ad = ((TypeStruct *)t)->sym;
L1:
if (ad && ad->aliasthis)
if (ad && ad->aliasthis)
{
bool isstatic = (e->op == TOKtype);
e = new DotIdExp(e->loc, e, ad->aliasthis->ident);
e = e->semantic(sc);
if (isstatic && ad->aliasthis->needThis())
{
bool isstatic = (e->op == TOKtype);
e = new DotIdExp(e->loc, e, ad->aliasthis->ident);
e = e->semantic(sc);
if (isstatic && ad->aliasthis->needThis())
{
/* non-@property function is not called inside typeof(),
* so resolve it ahead.
*/
int save = sc->intypeof;
sc->intypeof = 1; // bypass "need this" error check
e = resolveProperties(sc, e);
sc->intypeof = save;
e = new TypeExp(e->loc, new TypeTypeof(e->loc, e));
e = e->semantic(sc);
}
/* non-@property function is not called inside typeof(),
* so resolve it ahead.
*/
int save = sc->intypeof;
sc->intypeof = 1; // bypass "need this" error check
e = resolveProperties(sc, e);
sc->intypeof = save;
e = new TypeExp(e->loc, new TypeTypeof(e->loc, e));
e = e->semantic(sc);
}
e = resolveProperties(sc, e);
}
return e;
@@ -88,7 +78,8 @@ void AliasThis::semantic(Scope *sc)
assert(ad->members);
Dsymbol *s = ad->search(loc, ident, 0);
if (!s)
{ s = sc->search(loc, ident, NULL);
{
s = sc->search(loc, ident, NULL);
if (s)
::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
else
@@ -98,17 +89,24 @@ void AliasThis::semantic(Scope *sc)
else if (ad->aliasthis && s != ad->aliasthis)
error("there can be only one alias this");
if (ad->type->ty == Tstruct && ((TypeStruct *)ad->type)->sym != ad)
{
AggregateDeclaration *ad2 = ((TypeStruct *)ad->type)->sym;
assert(ad2->type == Type::terror);
ad->aliasthis = ad2->aliasthis;
return;
}
/* disable the alias this conversion so the implicit conversion check
* doesn't use it.
*/
/* This should use ad->aliasthis directly, but with static foreach and templates
* ad->type->sym might be different to ad.
*/
AggregateDeclaration *ad2 = ad->type->toDsymbol(NULL)->isAggregateDeclaration();
Dsymbol *save = ad2->aliasthis;
ad2->aliasthis = NULL;
ad->aliasthis = NULL;
if (Declaration *d = s->isDeclaration())
Dsymbol *sx = s;
if (sx->isAliasDeclaration())
sx = sx->toAlias();
Declaration *d = sx->isDeclaration();
if (d && !d->isTupleDeclaration())
{
Type *t = d->type;
assert(t);
@@ -118,7 +116,6 @@ void AliasThis::semantic(Scope *sc)
}
}
ad2->aliasthis = save;
ad->aliasthis = s;
}
else
@@ -136,5 +133,3 @@ void AliasThis::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring(ident->toChars());
buf->writestring(" this;\n");
}
#endif
-4
View File
@@ -20,8 +20,6 @@
/**************************************************************/
#if DMDV2
class AliasThis : public Dsymbol
{
public:
@@ -38,5 +36,3 @@ public:
};
#endif
#endif
+6 -12
View File
@@ -99,7 +99,7 @@ TypeTuple *TypeBasic::toArgTypes()
t2 = Type::tfloat80;
break;
case Tascii:
case Tchar:
t1 = Type::tuns8;
break;
@@ -127,16 +127,13 @@ TypeTuple *TypeBasic::toArgTypes()
return t;
}
#if DMDV2
TypeTuple *TypeVector::toArgTypes()
{
return new TypeTuple(this);
}
#endif
TypeTuple *TypeSArray::toArgTypes()
{
#if DMDV2
if (dim)
{
/* Should really be done as if it were a struct with dim members
@@ -149,9 +146,6 @@ TypeTuple *TypeSArray::toArgTypes()
return next->toArgTypes();
}
return new TypeTuple(); // pass on the stack for efficiency
#else
return new TypeTuple(); // pass on the stack for efficiency
#endif
}
TypeTuple *TypeAArray::toArgTypes()
@@ -204,8 +198,8 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2)
if (!t2)
return t1;
unsigned sz1 = t1->size(Loc());
unsigned sz2 = t2->size(Loc());
unsigned sz1 = (unsigned)t1->size(Loc());
unsigned sz2 = (unsigned)t2->size(Loc());
if (t1->ty != t2->ty &&
(t1->ty == Tfloat80 || t2->ty == Tfloat80))
@@ -265,7 +259,7 @@ TypeTuple *TypeDArray::toArgTypes()
if (global.params.is64bit && !global.params.isLP64)
{
// For AMD64 ILP32 ABI, D arrays fit into a single integer register.
unsigned offset = Type::tsize_t->size(Loc());
unsigned offset = (unsigned)Type::tsize_t->size(Loc());
Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
if (t)
return new TypeTuple(t);
@@ -281,7 +275,7 @@ TypeTuple *TypeDelegate::toArgTypes()
if (global.params.is64bit && !global.params.isLP64)
{
// For AMD64 ILP32 ABI, delegates fit into a single integer register.
unsigned offset = Type::tsize_t->size(Loc());
unsigned offset = (unsigned)Type::tsize_t->size(Loc());
Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
if (t)
return new TypeTuple(t);
@@ -360,7 +354,7 @@ TypeTuple *TypeStruct::toArgTypes()
goto Lmemory;
// Fields that overlap the 8byte boundary goto Lmemory
unsigned fieldsz = f->type->size(Loc());
d_uns64 fieldsz = f->type->size(Loc());
if (f->offset < 8 && (f->offset + fieldsz) > 8)
goto Lmemory;
}
+36 -34
View File
@@ -272,23 +272,12 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
* return p;
*/
Parameter *p = (*fparams)[0 /*fparams->dim - 1*/];
#if DMDV1
// for (size_t i = 0; i < p.length; i++)
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
Statement *s1 = new ForStatement(0,
new ExpStatement(0, d),
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
new ExpStatement(0, loopbody));
#else
// foreach (i; 0 .. p.length)
Statement *s1 = new ForeachRangeStatement(Loc(), TOKforeach,
new Parameter(0, NULL, Id::p, NULL),
new IntegerExp(Loc(), 0, Type::tsize_t),
new ArrayLengthExp(Loc(), new IdentifierExp(Loc(), p->ident)),
new ExpStatement(Loc(), loopbody));
#endif
//printf("%s\n", s1->toChars());
Statement *s2 = new ReturnStatement(Loc(), new IdentifierExp(Loc(), p->ident));
//printf("s2: %s\n", s2->toChars());
@@ -316,7 +305,14 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
sc->linkage = LINKc;
fd->semantic(sc);
fd->semantic2(sc);
unsigned errors = global.startGagging();
fd->semantic3(sc);
if (global.endGagging(errors))
{
fd->type = Type::terror;
fd->errors = true;
fd->fbody = NULL;
}
sc->pop();
if (op->cFunc)
@@ -344,6 +340,7 @@ bool isArrayOpValid(Expression *e)
}
Type *tb = e->type->toBasetype();
BinExp *be;
if ( (tb->ty == Tarray) || (tb->ty == Tsarray) )
{
switch (e->op)
@@ -365,11 +362,14 @@ bool isArrayOpValid(Expression *e)
case TOKxorass:
case TOKandass:
case TOKorass:
#if DMDV2
case TOKpow:
case TOKpowass:
#endif
return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2);
be = (BinExp *)e;
return isArrayOpValid(be->e1) && isArrayOpValid(be->e2);
case TOKconstruct:
be = (BinExp *)e;
return be->e1->op == TOKslice && isArrayOpValid(be->e2);
case TOKcall:
return false; // TODO: Decide if [] is required after arrayop calls.
@@ -395,15 +395,15 @@ Expression *BinExp::arrayOp(Scope *sc)
Type *tb = type->toBasetype();
assert(tb->ty == Tarray || tb->ty == Tsarray);
if (tb->nextOf()->toBasetype()->ty == Tvoid)
Type *tbn = tb->nextOf()->toBasetype();
if (tbn->ty == Tvoid)
{
error("Cannot perform array operations on void[] arrays");
return new ErrorExp();
}
if (!isArrayOpValid(e2))
if (!isArrayOpValid(this))
{
e2->error("invalid array operation %s (did you forget a [] ?)", toChars());
error("invalid array operation %s (did you forget a [] ?)", toChars());
return new ErrorExp();
}
@@ -420,11 +420,7 @@ Expression *BinExp::arrayOp(Scope *sc)
/* Append deco of array element type
*/
#if DMDV2
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
#else
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
#endif
buf.writeByte(0);
char *name = buf.toChars();
@@ -440,6 +436,20 @@ Expression *BinExp::arrayOp(Scope *sc)
if (!op)
op = buildArrayOp(ident, this, sc, loc);
if (op->dFunc && op->dFunc->errors)
{
const char *fmt;
if (tbn->ty == Tstruct || tbn->ty == Tclass)
fmt = "invalid array operation '%s' because %s doesn't support necessary arithmetic operations";
else if (!tbn->isscalar())
fmt = "invalid array operation '%s' because %s is not a scalar type";
else
fmt = "invalid array operation '%s' for element type %s";
error(fmt, toChars(), tbn->toChars());
return new ErrorExp();
}
*pOp = op;
FuncDeclaration *fd = op->cFunc ? op->cFunc : op->dFunc;
@@ -462,6 +472,10 @@ Expression *BinAssignExp::arrayOp(Scope *sc)
error("slice %s is not mutable", e1->toChars());
return new ErrorExp();
}
if (e1->op == TOKarrayliteral)
{
return e1->modifiableLvalue(sc, e1);
}
return BinExp::arrayOp(sc);
}
@@ -526,9 +540,7 @@ void BinAssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
case TOKxorass: s = "Xorass"; break;
case TOKandass: s = "Andass"; break;
case TOKorass: s = "Orass"; break;
#if DMDV2
case TOKpowass: s = "Powass"; break;
#endif
default: assert(0);
}
buf->writestring(s);
@@ -561,9 +573,7 @@ void BinExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
case TOKxor: s = "Xor"; break;
case TOKand: s = "And"; break;
case TOKor: s = "Or"; break;
#if DMDV2
case TOKpow: s = "Pow"; break;
#endif
default: break;
}
if (s)
@@ -632,14 +642,12 @@ Expression *AssignExp::buildArrayLoop(Parameters *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(Loc(), ex2, e1->type->nextOf());
#endif
Expression *ex1 = e1->buildArrayLoop(fparams);
Parameter *param = (*fparams)[0];
param->storageClass = 0;
@@ -666,9 +674,7 @@ Expression *BinAssignExp::buildArrayLoop(Parameters *fparams)
case TOKxorass: return new XorAssignExp(loc, ex1, ex2);
case TOKandass: return new AndAssignExp(loc, ex1, ex2);
case TOKorass: return new OrAssignExp(loc, ex1, ex2);
#if DMDV2
case TOKpowass: return new PowAssignExp(loc, ex1, ex2);
#endif
default:
assert(0);
return NULL;
@@ -701,9 +707,7 @@ Expression *BinExp::buildArrayLoop(Parameters *fparams)
case TOKxor:
case TOKand:
case TOKor:
#if DMDV2
case TOKpow:
#endif
{
/* Evaluate assign expressions left to right
*/
@@ -755,10 +759,8 @@ int Expression::isArrayOperand()
case TOKxorass:
case TOKandass:
case TOKorass:
#if DMDV2
case TOKpow:
case TOKpowass:
#endif
case TOKneg:
case TOKtilde:
return 1;
+4 -2
View File
@@ -56,14 +56,16 @@ typedef Array<class AliasDeclaration> AliasDeclarations;
typedef Array<class Module> Modules;
typedef Array<class File> Files;
typedef Array<struct File> Files;
typedef Array<class CaseStatement> CaseStatements;
typedef Array<class CompoundStatement> CompoundStatements;
typedef Array<class ScopeStatement> ScopeStatements;
typedef Array<class GotoCaseStatement> GotoCaseStatements;
typedef Array<class GotoStatement> GotoStatements;
typedef Array<class ReturnStatement> ReturnStatements;
typedef Array<class TemplateInstance> TemplateInstances;
+25 -14
View File
@@ -207,7 +207,7 @@ void AttribDeclaration::inlineScan()
}
}
void AttribDeclaration::addComment(utf8_t *comment)
void AttribDeclaration::addComment(const utf8_t *comment)
{
//printf("AttribDeclaration::addComment %s\n", comment);
if (comment)
@@ -288,10 +288,10 @@ bool AttribDeclaration::hasStaticCtorOrDtor()
{
Dsymbol *s = (*d)[i];
if (s->hasStaticCtorOrDtor())
return TRUE;
return true;
}
}
return FALSE;
return false;
}
const char *AttribDeclaration::kind()
@@ -497,11 +497,11 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
{ STCalias, TOKalias },
{ STCout, TOKout },
{ STCin, TOKin },
#if DMDV2
{ STCmanifest, TOKenum },
{ STCimmutable, TOKimmutable },
{ STCshared, TOKshared },
{ STCnothrow, TOKnothrow },
{ STCwild, TOKwild },
{ STCpure, TOKpure },
{ STCref, TOKref },
{ STCtls },
@@ -511,7 +511,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
{ STCtrusted, TOKat, "trusted" },
{ STCsystem, TOKat, "system" },
{ STCdisable, TOKat, "disable" },
#endif
};
for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
@@ -525,7 +524,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
return "__thread";
TOK tok = table[i].tok;
#if DMDV2
if (tok == TOKat)
{
tmp[0] = '@';
@@ -533,7 +531,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
return tmp;
}
else
#endif
return Token::toChars(tok);
}
}
@@ -741,6 +738,12 @@ void ProtDeclaration::semantic(Scope *sc)
}
}
void ProtDeclaration::emitComment(Scope *sc)
{
if (protection != PROTprivate)
AttribDeclaration::emitComment(sc);
}
void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, PROT protection)
{
const char *p;
@@ -1080,7 +1083,6 @@ void PragmaDeclaration::semantic(Scope *sc)
}
goto Lnodecl;
}
#if DMDV2
else if (ident == Id::startaddress)
{
if (!args || args->dim != 1)
@@ -1102,7 +1104,6 @@ void PragmaDeclaration::semantic(Scope *sc)
}
goto Lnodecl;
}
#endif
else if (ident == Id::mangle)
{
if (!args || args->dim != 1)
@@ -1388,7 +1389,7 @@ void ConditionalDeclaration::importAll(Scope *sc)
}
}
void ConditionalDeclaration::addComment(utf8_t *comment)
void ConditionalDeclaration::addComment(const utf8_t *comment)
{
/* Because addComment is called by the parser, if we called
* include() it would define a version before it was used.
@@ -1605,7 +1606,8 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
this->sd = sd;
if (memnum == 0)
{ /* No members yet, so parse the mixin now
{
/* No members yet, so parse the mixin now
*/
compileIt(sc);
memnum |= AttribDeclaration::addMember(sc, sd, memnum);
@@ -1624,13 +1626,13 @@ void CompileDeclaration::compileIt(Scope *sc)
exp = exp->ctfeInterpret();
StringExp *se = exp->toString();
if (!se)
{ exp->error("argument to mixin must be a string, not (%s)", exp->toChars());
{
exp->error("argument to mixin must be a string, not (%s)", exp->toChars());
}
else
{
se = se->toUTF8(sc);
Parser p(sc->module, (utf8_t *)se->string, se->len, 0);
p.scanloc = loc;
Parser p(loc, sc->module, (utf8_t *)se->string, se->len, 0);
p.nextToken();
unsigned errors = global.errors;
decl = p.parseDeclDefs(0);
@@ -1650,6 +1652,15 @@ void CompileDeclaration::semantic(Scope *sc)
compileIt(sc);
AttribDeclaration::addMember(sc, sd, 0);
compiled = 1;
if (scope && decl)
{
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = (*decl)[i];
s->setScope(scope);
}
}
}
AttribDeclaration::semantic(sc);
}
+3 -2
View File
@@ -46,7 +46,7 @@ public:
void semantic2(Scope *sc);
void semantic3(Scope *sc);
void inlineScan();
void addComment(utf8_t *comment);
void addComment(const utf8_t *comment);
void emitComment(Scope *sc);
const char *kind();
bool oneMember(Dsymbol **ps, Identifier *ident);
@@ -119,6 +119,7 @@ public:
void importAll(Scope *sc);
void setScope(Scope *sc);
void semantic(Scope *sc);
void emitComment(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void protectionToCBuffer(OutBuffer *buf, PROT protection);
@@ -184,7 +185,7 @@ public:
bool oneMember(Dsymbol **ps, Identifier *ident);
void emitComment(Scope *sc);
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
void addComment(utf8_t *comment);
void addComment(const utf8_t *comment);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
void importAll(Scope *sc);
-3
View File
@@ -24,7 +24,6 @@
#include "id.h"
#include "module.h"
#if DMDV2
/**********************************
* Determine if function is a builtin one that we can
@@ -222,5 +221,3 @@ Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments)
}
return e;
}
#endif
+12 -12
View File
@@ -23,7 +23,7 @@
#include "scope.h"
#include "attrib.h"
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow);
bool Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow);
int lambdaCanThrow(Expression *e, void *param);
/********************************************
@@ -40,11 +40,11 @@ struct CanThrow
bool mustnot;
};
int Expression::canThrow(bool mustNotThrow)
bool Expression::canThrow(bool mustNotThrow)
{
//printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars());
CanThrow ct;
ct.can = FALSE;
ct.can = false;
ct.mustnot = mustNotThrow;
apply(&lambdaCanThrow, &ct);
return ct.can;
@@ -81,7 +81,7 @@ int lambdaCanThrow(Expression *e, void *param)
{
if (pct->mustnot)
e->error("'%s' is not nothrow", ce->f ? ce->f->toPrettyChars() : ce->e1->toChars());
pct->can = TRUE;
pct->can = true;
}
break;
}
@@ -97,7 +97,7 @@ int lambdaCanThrow(Expression *e, void *param)
{
if (pct->mustnot)
e->error("constructor %s is not nothrow", ne->member->toChars());
pct->can = TRUE;
pct->can = true;
}
}
// regard storage allocation failures as not recoverable
@@ -126,7 +126,7 @@ int lambdaCanThrow(Expression *e, void *param)
{
if (pct->mustnot)
e->error("'%s' is not nothrow", sd->postblit->toPrettyChars());
pct->can = TRUE;
pct->can = true;
}
break;
}
@@ -146,7 +146,7 @@ int lambdaCanThrow(Expression *e, void *param)
* Mirrors logic in Dsymbol_toElem().
*/
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
bool Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
{
AttribDeclaration *ad;
VarDeclaration *vd;
@@ -164,7 +164,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
{
s = (*decl)[i];
if (Dsymbol_canThrow(s, mustNotThrow))
return 1;
return true;
}
}
}
@@ -182,7 +182,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
if (vd->init)
{ ExpInitializer *ie = vd->init->isExpInitializer();
if (ie && ie->exp->canThrow(mustNotThrow))
return 1;
return true;
}
if (vd->edtor && !vd->noscope)
return vd->edtor->canThrow(mustNotThrow);
@@ -197,7 +197,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
{
Dsymbol *sm = (*tm->members)[i];
if (Dsymbol_canThrow(sm, mustNotThrow))
return 1;
return true;
}
}
}
@@ -210,10 +210,10 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
if (eo->op == TOKdsymbol)
{ DsymbolExp *se = (DsymbolExp *)eo;
if (Dsymbol_canThrow(se->s, mustNotThrow))
return 1;
return true;
}
}
}
}
return 0;
return false;
}
+62 -73
View File
@@ -39,45 +39,12 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
MATCH match = implicitConvTo(t);
if (match)
{
#if DMDV1
TY tyfrom = type->toBasetype()->ty;
TY tyto = t->toBasetype()->ty;
if (global.params.warnings &&
Type::impcnvWarn[tyfrom][tyto] &&
op != TOKint64)
{
Expression *e = optimize(WANTflags | WANTvalue);
if (e->op == TOKint64)
return e->implicitCastTo(sc, t);
if (tyfrom == Tint32 &&
(op == TOKadd || op == TOKmin ||
op == TOKand || op == TOKor || op == TOKxor)
)
{
/* This is really only a semi-kludge fix,
* we really should look at the operands of op
* and see if they are narrower types.
* For example, b=b|b and b=b|7 and s=b+b should be allowed,
* but b=b|i should be an error.
*/
;
}
else
{
warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data",
toChars(), type->toChars(), t->toChars());
}
}
#endif
#if DMDV2
if (match == MATCHconst && type->constConv(t))
{
Expression *e = copy();
e->type = t;
return e;
}
#endif
return castTo(sc, t);
}
@@ -178,9 +145,8 @@ MATCH Expression::implicitConvTo(Type *t)
if (type->isintegral() && t->isintegral() &&
type->isTypeBasic() && t->isTypeBasic())
{ IntRange src = this->getIntRange() DUMP;
IntRange targetUnsigned = IntRange::fromType(t, /*isUnsigned*/true) DUMP;
IntRange targetSigned = IntRange::fromType(t, /*isUnsigned*/false) DUMP;
if (targetUnsigned.contains(src) || targetSigned.contains(src))
IntRange target = IntRange::fromType(t) DUMP;
if (target.contains(src))
return MATCHconvert;
}
@@ -226,6 +192,8 @@ MATCH IntegerExp::implicitConvTo(Type *t)
if (t->ty == Tvector)
{ TypeVector *tv = (TypeVector *)t;
TypeBasic *tb = tv->elementType();
if (tb->ty == Tvoid)
goto Lno;
toty = tb->ty;
}
@@ -442,7 +410,6 @@ MATCH NullExp::implicitConvTo(Type *t)
return Expression::implicitConvTo(t);
}
#if DMDV2
MATCH StructLiteralExp::implicitConvTo(Type *t)
{
#if 0
@@ -471,7 +438,6 @@ MATCH StructLiteralExp::implicitConvTo(Type *t)
}
return m;
}
#endif
MATCH StringExp::implicitConvTo(Type *t)
{
@@ -645,6 +611,27 @@ MATCH AssocArrayLiteralExp::implicitConvTo(Type *t)
return Expression::implicitConvTo(t);
}
Expression *CallExp::implicitCastTo(Scope *sc, Type *t)
{
//printf("CallExp::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars());
/* Allow the result of strongly pure functions to
* convert to immutable
*/
if (f && f->isolateReturn() &&
type->immutableOf()->equals(t->immutableOf()))
{
/* Avoid emitting CastExp for:
* T[] make() pure { ... }
* immutable T[] arr = make(); // unique return
*/
Expression *e = copy();
e->type = t;
return e;
}
return Expression::implicitCastTo(sc, t);
}
MATCH CallExp::implicitConvTo(Type *t)
{
#if 0
@@ -1025,7 +1012,7 @@ Type *SliceExp::toStaticArrayType()
Expression *upr = this->upr->optimize(WANTvalue);
if (lwr->isConst() && upr->isConst())
{
size_t len = upr->toUInteger() - lwr->toUInteger();
size_t len = (size_t)(upr->toUInteger() - lwr->toUInteger());
return TypeSArray::makeType(loc, type->toBasetype()->nextOf(), len);
}
}
@@ -1086,19 +1073,8 @@ Expression *Expression::castTo(Scope *sc, Type *t)
{
//printf("Converting [dim] to *\n");
if (typeb->size(loc) == 0)
e = new NullExp(loc);
else
e = new AddrExp(loc, e);
e = new AddrExp(loc, e);
}
#if 0
else if (tb->ty == Tdelegate && type->ty != Tdelegate)
{
TypeDelegate *td = (TypeDelegate *)tb;
TypeFunction *tf = (TypeFunction *)td->nextOf();
return toDelegate(sc, tf->nextOf());
}
#endif
else
{
if (typeb->ty == Tstruct)
@@ -1147,7 +1123,7 @@ Expression *Expression::castTo(Scope *sc, Type *t)
}
else if (typeb->implicitConvTo(tb) == MATCHconst && t->equals(type->constOf()))
{
Expression *e = copy();
e = copy();
e->type = t;
return e;
}
@@ -1480,7 +1456,7 @@ L2:
// See if need to truncate or extend the literal
if (tb->ty == Tsarray)
{
dinteger_t dim2 = ((TypeSArray *)tb)->dim->toInteger();
size_t dim2 = (size_t)((TypeSArray *)tb)->dim->toInteger();
//printf("dim from = %d, to = %d\n", (int)se->len, (int)dim2);
@@ -1744,9 +1720,7 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
e = new SymOffExp(loc, f, 0);
e->type = t;
}
#if DMDV2
f->tookAddressOf++;
#endif
return e;
}
}
@@ -1965,7 +1939,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
{
if (to->ty == Tdelegate ||
to->ty == Tpointer && to->nextOf()->ty == Tfunction)
{ fd->treq = to;
{
fd->treq = to;
}
return this;
}
@@ -1985,7 +1960,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
}
if (td)
{ /// Parameter types inference from
{
// Parameter types inference from 'to'
assert(td->scope);
if (t->ty == Tfunction)
{
@@ -2005,10 +1981,12 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
{
TemplateParameter *tp = (*td->parameters)[i];
for (size_t u = 0; u < dim; u++)
{ Parameter *p = Parameter::getNth(tfl->parameters, u);
{
Parameter *p = Parameter::getNth(tfl->parameters, u);
if (p->type->ty == Tident &&
((TypeIdentifier *)p->type)->ident == tp->ident)
{ p = Parameter::getNth(tfv->parameters, u);
{
p = Parameter::getNth(tfv->parameters, u);
Type *tprm = p->type;
if (tprm->reliesOnTident(tparams))
goto L1;
@@ -2036,7 +2014,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
fld->treq = NULL;
if (e->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)e;
{
FuncExp *fe = (FuncExp *)e;
assert(fe->td == NULL);
e = fe->inferType(to, flag);
}
@@ -2065,7 +2044,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
}
L1:
if (!flag && !e)
{ error("cannot infer function literal type from %s", to->toChars());
{
error("cannot infer function literal type from %s", to->toChars());
e = new ErrorExp();
}
return e;
@@ -2700,6 +2680,15 @@ Lcc:
e2 = e2->castTo(sc, t);
goto Lagain;
}
else if (t1->ty == Tnull && t2->ty == Tnull)
{
unsigned char mod = MODmerge(t1->mod, t2->mod);
t = t1->castMod(mod);
e1 = e1->castTo(sc, t);
e2 = e2->castTo(sc, t);
goto Lret;
}
else if (e1->isArrayOperand() && t1->ty == Tarray &&
e2->implicitConvTo(t1->nextOf()))
{ // T[] op T
@@ -2770,6 +2759,8 @@ Expression *BinExp::typeCombine(Scope *sc)
goto Lerror;
else if (t1->ty == Tclass && t2->ty == Tclass)
goto Lerror;
else if (t1->ty == Taarray && t2->ty == Taarray)
goto Lerror;
}
if (!typeMerge(sc, this, &type, &e1, &e2))
@@ -2930,12 +2921,11 @@ IntRange DivExp::getIntRange()
return Expression::getIntRange() DUMP;
// [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)]
SignExtendedNumber bdy[4] = {
ir1.imin / ir2.imin,
ir1.imin / ir2.imax,
ir1.imax / ir2.imin,
ir1.imax / ir2.imax
};
SignExtendedNumber bdy[4];
bdy[0] = ir1.imin / ir2.imin;
bdy[1] = ir1.imin / ir2.imax;
bdy[2] = ir1.imax / ir2.imin;
bdy[3] = ir1.imax / ir2.imax;
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
}
@@ -2945,12 +2935,11 @@ IntRange MulExp::getIntRange()
IntRange ir2 = e2->getIntRange();
// [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)]
SignExtendedNumber bdy[4] = {
ir1.imin * ir2.imin,
ir1.imin * ir2.imax,
ir1.imax * ir2.imin,
ir1.imax * ir2.imax
};
SignExtendedNumber bdy[4];
bdy[0] = ir1.imin * ir2.imin;
bdy[1] = ir1.imin * ir2.imax;
bdy[2] = ir1.imax * ir2.imin;
bdy[3] = ir1.imax * ir2.imax;
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
}
+23 -32
View File
@@ -155,7 +155,6 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
Type::typeinfotypelist = this;
}
#if DMDV2
if (id == Id::TypeInfo_Const)
{ if (!inObject)
error("%s", msg);
@@ -185,7 +184,6 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
error("%s", msg);
Type::typeinfovector = this;
}
#endif
}
if (id == Id::Object)
@@ -213,16 +211,8 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
}
#if !MODULEINFO_IS_STRUCT
#ifdef DMDV2
if (id == Id::ModuleInfo && !Module::moduleinfo)
Module::moduleinfo = this;
#else
if (id == Id::ModuleInfo)
{ if (Module::moduleinfo)
error("%s", msg);
Module::moduleinfo = this;
}
#endif
#endif
}
@@ -381,10 +371,21 @@ void ClassDeclaration::semantic(Scope *sc)
goto L7;
}
}
if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
{ // Try to resolve forward reference
if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope)
tc->sym->semantic(NULL);
if (tc->sym->scope)
{
// Try to resolve forward reference
tc->sym->semantic(NULL);
}
if (tc->sym->symtab && tc->sym->scope == NULL)
{
/* Bugzilla 11034: Essentailly, class inheritance hierarchy
* and instance size of each classes are orthogonal information.
* Therefore, even if tc->sym->sizeof == SIZEOKnone,
* we need to set baseClass field for class covariance check.
*/
baseClass = tc->sym;
b->base = baseClass;
}
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
{
@@ -399,10 +400,6 @@ void ClassDeclaration::semantic(Scope *sc)
scope->module->addDeferredSemantic(this);
return;
}
else
{ baseClass = tc->sym;
b->base = baseClass;
}
L7: ;
}
}
@@ -448,10 +445,10 @@ void ClassDeclaration::semantic(Scope *sc)
error("inherits from duplicate interface %s", b2->base->toChars());
}
if (!tc->sym->symtab)
{ // Try to resolve forward reference
if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope)
tc->sym->semantic(NULL);
if (tc->sym->scope)
{
// Try to resolve forward reference
tc->sym->semantic(NULL);
}
b->base = tc->sym;
@@ -999,7 +996,6 @@ ClassDeclaration *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
* Return 1 if function is hidden (not findable through search).
*/
#if DMDV2
int isf(void *param, Dsymbol *s)
{
FuncDeclaration *fd = s->isFuncDeclaration();
@@ -1044,7 +1040,6 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
return !fd->parent->isTemplateMixin();
}
}
#endif
/****************
* Find virtual function matching identifier and type.
@@ -1172,7 +1167,6 @@ int ClassDeclaration::isCOMinterface()
return 0;
}
#if DMDV2
int ClassDeclaration::isCPPclass()
{
return cpp;
@@ -1182,7 +1176,6 @@ int ClassDeclaration::isCPPinterface()
{
return 0;
}
#endif
/****************************************
@@ -1366,10 +1359,10 @@ void InterfaceDeclaration::semantic(Scope *sc)
baseclasses->remove(i);
continue;
}
if (!b->base->symtab)
{ // Try to resolve forward reference
if (doAncestorsSemantic == SemanticIn && b->base->scope)
b->base->semantic(NULL);
if (b->base->scope)
{
// Try to resolve forward reference
b->base->semantic(NULL);
}
if (!b->base->symtab || b->base->scope || b->base->inuse)
{
@@ -1605,12 +1598,10 @@ int InterfaceDeclaration::isCOMinterface()
return com;
}
#if DMDV2
int InterfaceDeclaration::isCPPinterface()
{
return cpp;
}
#endif
/*******************************************
*/
+12 -11
View File
@@ -76,6 +76,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc)
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
sc = sc->push();
sc->tinst = NULL;
sc->speculative = true;
for (size_t i = 0; i < 2; i++)
@@ -196,7 +197,11 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
if (dtor || postblit)
{
if (dtor)
{
stc = mergeFuncAttrs(stc, dtor->storage_class);
if (stc & STCsafe)
stc = (stc & ~STCsafe) | STCtrusted;
}
}
else
{
@@ -241,7 +246,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
{
tmp = new VarDeclaration(loc, type, idtmp, new VoidInitializer(loc));
tmp->noscope = 1;
tmp->storage_class |= STCctfe;
tmp->storage_class |= STCtemp | STCctfe;
e = new DeclarationExp(loc, tmp);
ec = new AssignExp(loc,
new VarExp(loc, tmp),
@@ -305,7 +310,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
Dsymbols *decldefs = new Dsymbols();
decldefs->push(s);
TemplateDeclaration *tempdecl =
new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0);
new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs);
s = tempdecl;
}
#endif
@@ -419,6 +424,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
sc = sc->push();
sc->tinst = NULL;
sc->speculative = true;
for (size_t j = 0; j < 2; j++)
@@ -483,7 +489,7 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
{
TypeFunction *tfeqptr;
{
Scope sc;
Scope scx;
/* const bool opEquals(ref const S s);
*/
@@ -491,7 +497,7 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tfeqptr->mod = MODconst;
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &sc);
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &scx);
}
fd = fd->overloadExactMatch(tfeqptr);
if (fd)
@@ -569,7 +575,7 @@ FuncDeclaration *StructDeclaration::buildXopCmp(Scope *sc)
{
TypeFunction *tfcmpptr;
{
Scope sc;
Scope scx;
/* const int opCmp(ref const S s);
*/
@@ -577,7 +583,7 @@ FuncDeclaration *StructDeclaration::buildXopCmp(Scope *sc)
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
tfcmpptr = new TypeFunction(parameters, Type::tint32, 0, LINKd);
tfcmpptr->mod = MODconst;
tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &sc);
tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &scx);
}
fd = fd->overloadExactMatch(tfcmpptr);
if (fd)
@@ -758,7 +764,6 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
* and the ordering changes (runs forward instead of backwards).
*/
#if DMDV2
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
{
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
@@ -864,8 +869,6 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
}
}
#endif
/*****************************************
* Create inclusive destructor for struct/class by aggregating
* all the destructors in dtors[] with the destructors for
@@ -882,7 +885,6 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
Loc loc = Loc(); // internal code should have no loc to prevent coverage
Expression *e = NULL;
#if DMDV2
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields[i];
@@ -946,7 +948,6 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
members->push(dd);
dd->semantic(sc);
}
#endif
switch (dtors.dim)
{
+4 -4
View File
@@ -34,11 +34,11 @@ int findCondition(Strings *ids, Identifier *ident)
const char *id = (*ids)[i];
if (strcmp(id, ident->toChars()) == 0)
return TRUE;
return true;
}
}
return FALSE;
return false;
}
/* ============================================================ */
@@ -375,9 +375,9 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{
goto Lerror;
}
else if (e->isBool(TRUE))
else if (e->isBool(true))
inc = 1;
else if (e->isBool(FALSE))
else if (e->isBool(false))
inc = 2;
else
{
+30 -123
View File
@@ -14,10 +14,6 @@
#include <string.h> // mem{cpy|set|cmp}()
#include <math.h>
#if __DMC__
#include <complex.h>
#endif
#include "rmem.h"
#include "root.h"
#include "port.h"
@@ -185,17 +181,6 @@ Expression *Add(Type *type, Expression *e1, Expression *e2)
switch (x)
{
#if __DMC__
case 0+0: v = (complex_t) (r1 + r2); break;
case 0+1: v = r1 + i2 * I; break;
case 0+2: v = r1 + c2; break;
case 3+0: v = i1 * I + r2; break;
case 3+1: v = (complex_t) ((i1 + i2) * I); break;
case 3+2: v = i1 * I + c2; break;
case 6+0: v = c1 + r2; break;
case 6+1: v = c1 + i2 * I; break;
case 6+2: v = c1 + c2; break;
#else
case 0+0: v = complex_t(r1 + r2, 0); break;
case 0+1: v = complex_t(r1, i2); break;
case 0+2: v = complex_t(r1 + creall(c2), cimagl(c2)); break;
@@ -205,7 +190,6 @@ Expression *Add(Type *type, Expression *e1, Expression *e2)
case 6+0: v = complex_t(creall(c1) + r2, cimagl(c2)); break;
case 6+1: v = complex_t(creall(c1), cimagl(c1) + i2); break;
case 6+2: v = c1 + c2; break;
#endif
default: assert(0);
}
e = new ComplexExp(loc, v, type);
@@ -282,17 +266,6 @@ Expression *Min(Type *type, Expression *e1, Expression *e2)
switch (x)
{
#if __DMC__
case 0+0: v = (complex_t) (r1 - r2); break;
case 0+1: v = r1 - i2 * I; break;
case 0+2: v = r1 - c2; break;
case 3+0: v = i1 * I - r2; break;
case 3+1: v = (complex_t) ((i1 - i2) * I); break;
case 3+2: v = i1 * I - c2; break;
case 6+0: v = c1 - r2; break;
case 6+1: v = c1 - i2 * I; break;
case 6+2: v = c1 - c2; break;
#else
case 0+0: v = complex_t(r1 - r2, 0); break;
case 0+1: v = complex_t(r1, -i2); break;
case 0+2: v = complex_t(r1 - creall(c2), -cimagl(c2)); break;
@@ -302,7 +275,6 @@ Expression *Min(Type *type, Expression *e1, Expression *e2)
case 6+0: v = complex_t(creall(c1) - r2, cimagl(c1)); break;
case 6+1: v = complex_t(creall(c1), cimagl(c1) - i2); break;
case 6+2: v = c1 - c2; break;
#endif
default: assert(0);
}
e = new ComplexExp(loc, v, type);
@@ -330,43 +302,27 @@ Expression *Mul(Type *type, Expression *e1, Expression *e2)
if (e1->type->isreal())
{
#if __DMC__
c = e1->toReal() * e2->toComplex();
#else
r = e1->toReal();
c = e2->toComplex();
c = complex_t(r * creall(c), r * cimagl(c));
#endif
}
else if (e1->type->isimaginary())
{
#if __DMC__
c = e1->toImaginary() * I * e2->toComplex();
#else
r = e1->toImaginary();
c = e2->toComplex();
c = complex_t(-r * cimagl(c), r * creall(c));
#endif
}
else if (e2->type->isreal())
{
#if __DMC__
c = e2->toReal() * e1->toComplex();
#else
r = e2->toReal();
c = e1->toComplex();
c = complex_t(r * creall(c), r * cimagl(c));
#endif
}
else if (e2->type->isimaginary())
{
#if __DMC__
c = e1->toComplex() * e2->toImaginary() * I;
#else
r = e2->toImaginary();
c = e1->toComplex();
c = complex_t(-r * cimagl(c), r * creall(c));
#endif
}
else
c = e1->toComplex() * e2->toComplex();
@@ -404,31 +360,15 @@ Expression *Div(Type *type, Expression *e1, Expression *e2)
e = new RealExp(loc, e1->toReal() / e2->toReal(), type);
return e;
}
#if __DMC__
//r = e2->toReal();
//c = e1->toComplex();
//printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r);
c = e1->toComplex() / e2->toReal();
#else
r = e2->toReal();
c = e1->toComplex();
c = complex_t(creall(c) / r, cimagl(c) / r);
#endif
}
else if (e2->type->isimaginary())
{
#if __DMC__
//r = e2->toImaginary();
//c = e1->toComplex();
//printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r);
c = e1->toComplex() / (e2->toImaginary() * I);
#else
r = e2->toImaginary();
c = e1->toComplex();
c = complex_t(cimagl(c) / r, -creall(c) / r);
#endif
}
else
{
@@ -476,20 +416,12 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
if (e2->type->isreal())
{ real_t r2 = e2->toReal();
#ifdef __DMC__
c = Port::fmodl(e1->toReal(), r2) + Port::fmodl(e1->toImaginary(), r2) * I;
#else
c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2));
#endif
}
else if (e2->type->isimaginary())
{ real_t i2 = e2->toImaginary();
#ifdef __DMC__
c = Port::fmodl(e1->toReal(), i2) + Port::fmodl(e1->toImaginary(), i2) * I;
#else
c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2));
#endif
}
else
assert(0);
@@ -563,7 +495,12 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
else
neg = false;
if (e1->type->isfloating())
if (e1->type->iscomplex())
{
r = new ComplexExp(loc, e1->toComplex(), e1->type);
v = new ComplexExp(loc, complex_t(1.0, 0.0), e1->type);
}
else if (e1->type->isfloating())
{
r = new RealExp(loc, e1->toReal(), e1->type);
v = new RealExp(loc, ldouble(1.0), e1->type);
@@ -585,7 +522,9 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
if (neg)
v = Div(v->type, new RealExp(loc, ldouble(1.0), v->type), v);
if (type->isintegral())
if (type->iscomplex())
e = new ComplexExp(loc, v->toComplex(), type);
else if (type->isintegral())
e = new IntegerExp(loc, v->toInteger(), type);
else
e = new RealExp(loc, v->toReal(), type);
@@ -819,7 +758,7 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
if (v == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
cmp = v->toInteger();
cmp = (int)v->toInteger();
if (cmp == 0)
break;
}
@@ -885,7 +824,7 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
if (v == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
cmp = v->toInteger();
cmp = (int)v->toInteger();
if (cmp == 0)
break;
}
@@ -896,11 +835,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
cmp = 0;
}
}
#if 0 // Should handle this
else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
{
}
#endif
else if (e1->isConst() != 1 || e2->isConst() != 1)
return EXP_CANT_INTERPRET;
else if (e1->type->isreal())
@@ -914,9 +848,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
r1 = e1->toImaginary();
r2 = e2->toImaginary();
L1:
#if __DMC__
cmp = (r1 == r2);
#else
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
{
cmp = 0;
@@ -925,7 +856,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
{
cmp = (r1 == r2);
}
#endif
}
else if (e1->type->iscomplex())
{
@@ -1046,30 +976,8 @@ Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2)
r1 = e1->toImaginary();
r2 = e2->toImaginary();
L1:
#if __DMC__
// DMC is the only compiler I know of that handles NAN arguments
// correctly in comparisons.
switch (op)
{
case TOKlt: n = r1 < r2; break;
case TOKle: n = r1 <= r2; break;
case TOKgt: n = r1 > r2; break;
case TOKge: n = r1 >= r2; break;
case TOKleg: n = r1 <>= r2; break;
case TOKlg: n = r1 <> r2; break;
case TOKunord: n = r1 !<>= r2; break;
case TOKue: n = r1 !<> r2; break;
case TOKug: n = r1 !<= r2; break;
case TOKuge: n = r1 !< r2; break;
case TOKul: n = r1 !>= r2; break;
case TOKule: n = r1 !> r2; break;
default:
assert(0);
}
#else
// Don't rely on compiler, handle NAN arguments separately
// (DMC does do it correctly)
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
{
switch (op)
@@ -1114,7 +1022,6 @@ Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2)
assert(0);
}
}
#endif
}
else if (e1->type->iscomplex())
{
@@ -1362,7 +1269,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
}
else if (e1->op == TOKarrayliteral)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
e = (*ale->elements)[i];
e = (*ale->elements)[(size_t)i];
e->type = type;
e->loc = loc;
if (e->hasSideEffect())
@@ -1381,7 +1288,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
e = new ErrorExp();
}
else
{ e = (*ale->elements)[i];
{ e = (*ale->elements)[(size_t)i];
e->type = type;
e->loc = loc;
if (e->hasSideEffect())
@@ -1401,7 +1308,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2);
if (ex == EXP_CANT_INTERPRET)
return ex;
if (ex->isBool(TRUE))
if (ex->isBool(true))
{ e = (*ae->values)[i];
e->type = type;
e->loc = loc;
@@ -1441,8 +1348,8 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
else
{
void *s;
size_t len = iupr - ilwr;
int sz = es1->sz;
size_t len = (size_t)(iupr - ilwr);
unsigned char sz = es1->sz;
StringExp *es;
s = mem.malloc((len + 1) * sz);
@@ -1471,10 +1378,10 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
else
{
Expressions *elements = new Expressions();
elements->setDim(iupr - ilwr);
elements->setDim((size_t)(iupr - ilwr));
memcpy(elements->tdata(),
es1->elements->tdata() + ilwr,
(iupr - ilwr) * sizeof((*es1->elements)[0]));
(size_t)(iupr - ilwr) * sizeof((*es1->elements)[0]));
e = new ArrayLiteralExp(e1->loc, elements);
e->type = type;
}
@@ -1519,8 +1426,8 @@ void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *n
unsigned value = (unsigned)((*newae->elements)[j]->toInteger());
switch (existingSE->sz)
{
case 1: s[j+firstIndex] = value; break;
case 2: ((unsigned short *)s)[j+firstIndex] = value; break;
case 1: s[j+firstIndex] = (utf8_t)value; break;
case 2: ((unsigned short *)s)[j+firstIndex] = (unsigned short)value; break;
case 4: ((unsigned *)s)[j+firstIndex] = value; break;
default:
assert(0);
@@ -1609,11 +1516,11 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
StringExp *es;
if (t->nextOf())
t = t->nextOf()->toBasetype();
size_t sz = t->size();
unsigned char sz = (unsigned char)t->size();
dinteger_t v = e->toInteger();
size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, v);
size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, (dchar_t)v);
s = mem.malloc((len + 1) * sz);
if (t->ty == tn->ty)
#if IN_LLVM
@@ -1627,7 +1534,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
memcpy((utf8_t *)s, &v, sz);
#endif
else
utf_encode(sz, s, v);
utf_encode(sz, s, (dchar_t)v);
// Add terminating 0
memset((utf8_t *)s + len * sz, 0, sz);
@@ -1672,7 +1579,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
StringExp *es2 = (StringExp *)e2;
StringExp *es;
size_t len = es1->len + es2->len;
int sz = es1->sz;
unsigned char sz = es1->sz;
if (sz != es2->sz)
{
@@ -1737,14 +1644,14 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
void *s;
StringExp *es1 = (StringExp *)e1;
StringExp *es;
size_t sz = es1->sz;
unsigned char sz = es1->sz;
dinteger_t v = e2->toInteger();
// Is it a concatentation of homogenous types?
// (char[] ~ char, wchar[]~wchar, or dchar[]~dchar)
bool homoConcat = (sz == t2->size());
size_t len = es1->len;
len += homoConcat ? 1 : utf_codeLength(sz, v);
len += homoConcat ? 1 : utf_codeLength(sz, (dchar_t)v);
s = mem.malloc((len + 1) * sz);
memcpy(s, es1->string, es1->len * sz);
@@ -1760,7 +1667,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
memcpy((utf8_t *)s + (sz * es1->len), &v, sz);
#endif
else
utf_encode(sz, (utf8_t *)s + (sz * es1->len), v);
utf_encode(sz, (utf8_t *)s + (sz * es1->len), (dchar_t)v);
// Add terminating 0
memset((utf8_t *)s + len * sz, 0, sz);
@@ -1778,7 +1685,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
StringExp *es2 = (StringExp *)e2;
StringExp *es;
size_t len = 1 + es2->len;
int sz = es2->sz;
unsigned char sz = es2->sz;
dinteger_t v = e1->toInteger();
s = mem.malloc((len + 1) * sz);
@@ -1917,7 +1824,7 @@ Expression *Ptr(Type *type, Expression *e1)
{ AddrExp *ade = (AddrExp *)ae->e1;
if (ade->e1->op == TOKstructliteral)
{ StructLiteralExp *se = (StructLiteralExp *)ade->e1;
unsigned offset = ae->e2->toInteger();
unsigned offset = (unsigned)ae->e2->toInteger();
Expression *e = se->getField(type, offset);
if (!e)
e = EXP_CANT_INTERPRET;
+1 -1
View File
@@ -127,7 +127,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
/// Create a string literal consisting of 'value' duplicated 'dim' times.
StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
unsigned value, size_t dim, int sz);
unsigned value, size_t dim, unsigned char sz);
/* Set dest = src, where both dest and src are container value literals
+69 -52
View File
@@ -314,12 +314,13 @@ Expression *copyLiteral(Expression *e)
}
else if (e->op == TOKfunction || e->op == TOKdelegate
|| e->op == TOKsymoff || e->op == TOKnull
|| e->op == TOKvar
|| e->op == TOKvar || e->op == TOKdotvar
|| e->op == TOKint64 || e->op == TOKfloat64
|| e->op == TOKchar || e->op == TOKcomplex80
|| e->op == TOKvoid)
{ // Simple value types
Expression *r = e->syntaxCopy();
{
// Simple value types
Expression *r = e->copy(); // keep e1 for DelegateExp and DotVarExp
r->type = e->type;
return r;
}
@@ -331,12 +332,14 @@ Expression *copyLiteral(Expression *e)
else if (e->op == TOKindex)
r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2);
else if (e->op == TOKdotvar)
{
#if DMDV2
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1,
((DotVarExp *)e)->var, ((DotVarExp *)e)->hasOverloads);
#else
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var);
#endif
}
else
assert(0);
r->type = e->type;
@@ -470,7 +473,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
{
// If it is a multidimensional array literal, do it recursively
elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem,
((TypeSArray *)type->nextOf())->dim->toInteger());
(size_t)((TypeSArray *)type->nextOf())->dim->toInteger());
}
bool mustCopy = needToCopyLiteral(elem);
for (size_t i = 0; i < dim; i++)
@@ -489,15 +492,15 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
* Create a string literal consisting of 'value' duplicated 'dim' times.
*/
StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
unsigned value, size_t dim, int sz)
unsigned value, size_t dim, unsigned char sz)
{
utf8_t *s = (utf8_t *)mem.calloc(dim + 1, sz);
for (size_t elemi = 0; elemi < dim; ++elemi)
{
switch (sz)
{
case 1: s[elemi] = value; break;
case 2: ((unsigned short *)s)[elemi] = value; break;
case 1: s[elemi] = (utf8_t)value; break;
case 2: ((unsigned short *)s)[elemi] = (unsigned short)value; break;
case 4: ((unsigned *)s)[elemi] = value; break;
default: assert(0);
}
@@ -568,10 +571,10 @@ bool isPointer(Type *t)
return tb->ty == Tpointer && tb->nextOf()->ty != Tfunction;
}
// For CTFE only. Returns true if 'e' is TRUE or a non-null pointer.
// For CTFE only. Returns true if 'e' is true or a non-null pointer.
int isTrueBool(Expression *e)
{
return e->isBool(TRUE) || ((e->type->ty == Tpointer || e->type->ty == Tclass)
return e->isBool(true) || ((e->type->ty == Tpointer || e->type->ty == Tclass)
&& e->op != TOKnull);
}
@@ -786,7 +789,7 @@ int comparePointers(Loc loc, TOK op, Type *type, Expression *agg1, dinteger_t of
{
if ( pointToSameMemoryBlock(agg1, agg2) )
{
dinteger_t n;
int n;
switch(op)
{
case TOKlt: n = (ofs1 < ofs2); break;
@@ -880,7 +883,7 @@ Expression *paintFloatInt(Expression *fromVal, Type *to)
}
else
{
u.x = fromVal->toInteger();
u.x = (d_int32)fromVal->toInteger();
return new RealExp(fromVal->loc, ldouble(u.f), to);
}
}
@@ -1128,6 +1131,7 @@ bool isCtfeComparable(Expression *e)
x->op != TOKdelegate &&
x->op != TOKarrayliteral &&
x->op != TOKstructliteral &&
x->op != TOKassocarrayliteral &&
x->op != TOKclassreference)
{
return false;
@@ -1191,29 +1195,7 @@ int intSignedCmp(TOK op, sinteger_t n1, sinteger_t n2)
int realCmp(TOK op, real_t r1, real_t r2)
{
int n;
#if __DMC__
// DMC is the only compiler I know of that handles NAN arguments
// correctly in comparisons.
switch (op)
{
case TOKlt: n = r1 < r2; break;
case TOKle: n = r1 <= r2; break;
case TOKgt: n = r1 > r2; break;
case TOKge: n = r1 >= r2; break;
case TOKleg: n = r1 <>= r2; break;
case TOKlg: n = r1 <> r2; break;
case TOKunord: n = r1 !<>= r2; break;
case TOKue: n = r1 !<> r2; break;
case TOKug: n = r1 !<= r2; break;
case TOKuge: n = r1 !< r2; break;
case TOKul: n = r1 !>= r2; break;
case TOKule: n = r1 !> r2; break;
default:
assert(0);
}
#else
// Don't rely on compiler, handle NAN arguments separately
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
{
@@ -1259,7 +1241,6 @@ int realCmp(TOK op, real_t r1, real_t r2)
assert(0);
}
}
#endif
return n;
}
@@ -1294,11 +1275,11 @@ int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len)
// Now both must be either TOKarrayliteral or TOKstring
if (se1 && se2)
return sliceCmpStringWithString(se1, se2, lo1, lo2, len);
return sliceCmpStringWithString(se1, se2, (size_t)lo1, (size_t)lo2, (size_t)len);
if (se1 && ae2)
return sliceCmpStringWithArray(se1, ae2, lo1, lo2, len);
return sliceCmpStringWithArray(se1, ae2, (size_t)lo1, (size_t)lo2, (size_t)len);
if (se2 && ae1)
return -sliceCmpStringWithArray(se2, ae1, lo2, lo1, len);
return -sliceCmpStringWithArray(se2, ae1, (size_t)lo2, (size_t)lo1, (size_t)len);
assert (ae1 && ae2);
// Comparing two array literals. This case is potentially recursive.
@@ -1306,8 +1287,8 @@ int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len)
// a full cmp.
bool needCmp = ae1->type->nextOf()->isintegral();
for (size_t i = 0; i < len; i++)
{ Expression *ee1 = (*ae1->elements)[lo1 + i];
Expression *ee2 = (*ae2->elements)[lo2 + i];
{ Expression *ee1 = (*ae1->elements)[(size_t)(lo1 + i)];
Expression *ee2 = (*ae2->elements)[(size_t)(lo2 + i)];
if (needCmp)
{ sinteger_t c = ee1->toInteger() - ee2->toInteger();
if (c > 0)
@@ -1418,7 +1399,7 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
if (res != 0)
return res;
}
return len1 - len2;
return (int)(len1 - len2);
}
if (e1->type->isintegral())
{
@@ -1437,9 +1418,6 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
r1 = e1->toImaginary();
r2 = e2->toImaginary();
L1:
#if __DMC__
return (r1 != r2);
#else
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
{
return 1;
@@ -1448,7 +1426,6 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
{
return (r1 != r2);
}
#endif
}
else if (e1->type->iscomplex())
{
@@ -1486,6 +1463,43 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
return 0; // All elements are equal
}
}
if (e1->op == TOKassocarrayliteral && e2->op == TOKassocarrayliteral)
{
AssocArrayLiteralExp *es1 = (AssocArrayLiteralExp *)e1;
AssocArrayLiteralExp *es2 = (AssocArrayLiteralExp *)e2;
int dim = es1->keys->dim;
if (es2->keys->dim != dim)
return 1;
bool *used = (bool *)mem.malloc(sizeof(bool) * dim);
memset(used, 0, sizeof(bool) * dim);
for (size_t i = 0; i < dim; ++i)
{
Expression *k1 = (*es1->keys)[i];
Expression *v1 = (*es1->values)[i];
for (size_t j = 0; j < dim; ++j)
{
if (used[j])
continue;
Expression *k2 = (*es2->keys)[j];
Expression *v2 = (*es2->values)[j];
if (ctfeRawCmp(loc, k1, k2))
continue;
used[j] = true;
if (ctfeRawCmp(loc, v1, v2))
{
mem.free(used);
return 1;
}
}
}
mem.free(used);
return 0;
}
error(loc, "CTFE internal error: bad compare");
assert(0);
return 0;
@@ -1601,7 +1615,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
StringExp *es1 = (StringExp *)e2;
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1;
size_t len = es1->len + es2->elements->dim;
int sz = es1->sz;
unsigned char sz = es1->sz;
void *s = mem.malloc((len + 1) * sz);
memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz);
@@ -1641,7 +1655,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
StringExp *es1 = (StringExp *)e1;
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
size_t len = es1->len + es2->elements->dim;
int sz = es1->sz;
unsigned char sz = es1->sz;
void *s = mem.malloc((len + 1) * sz);
memcpy(s, es1->string, es1->len * sz);
@@ -1746,7 +1760,7 @@ Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx)
error(loc, "array index %llu is out of bounds %s[0 .. %llu]", indx, e1->toChars(), (ulonglong)ale->elements->dim);
return EXP_CANT_INTERPRET;
}
Expression *e = (*ale->elements)[indx];
Expression *e = (*ale->elements)[(size_t)indx];
return paintTypeOntoLiteral(type, e);
}
@@ -1949,7 +1963,7 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
// Resolve slices
size_t indxlo = 0;
if (oldval->op == TOKslice)
{ indxlo = ((SliceExp *)oldval)->lwr->toInteger();
{ indxlo = (size_t)((SliceExp *)oldval)->lwr->toInteger();
oldval = ((SliceExp *)oldval)->e1;
}
size_t copylen = oldlen < newlen ? oldlen : newlen;
@@ -1963,9 +1977,9 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
{
switch (oldse->sz)
{
case 1: s[indxlo + elemi] = defaultValue; break;
case 2: ((unsigned short *)s)[indxlo + elemi] = defaultValue; break;
case 4: ((unsigned *)s)[indxlo + elemi] = defaultValue; break;
case 1: s[(size_t)(indxlo + elemi)] = (utf8_t)defaultValue; break;
case 2: ((unsigned short *)s)[(size_t)(indxlo + elemi)] = (unsigned short)defaultValue; break;
case 4: ((unsigned *)s)[(size_t)(indxlo + elemi)] = defaultValue; break;
default: assert(0);
}
}
@@ -2069,6 +2083,9 @@ bool isCtfeValueValid(Expression *newval)
if (newval->op == TOKfunction)
return true; // function literal or delegate literal
if (newval->op == TOKvector)
return true; // vector literal
if (newval->op == TOKdelegate)
{
Expression *dge = ((DelegateExp *)newval)->e1;
@@ -2254,7 +2271,7 @@ Expression *TypeSArray::voidInitLiteral(VarDeclaration *var)
bool mustCopy = (elem->op == TOKarrayliteral || elem->op == TOKstructliteral);
Expressions *elements = new Expressions();
size_t d = dim->toInteger();
size_t d = (size_t)dim->toInteger();
elements->setDim(d);
for (size_t i = 0; i < d; i++)
{ if (mustCopy && i > 0)
+72 -265
View File
@@ -27,8 +27,6 @@
#include "ctfe.h"
#include "target.h"
AggregateDeclaration *isAggregate(Type *t); // from opover.c
void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad)
{
if (!ad->isNested())
@@ -99,7 +97,7 @@ const char *Declaration::kind()
unsigned Declaration::size(Loc loc)
{
assert(type);
return type->size();
return (unsigned)type->size();
}
bool Declaration::isDelete()
@@ -132,8 +130,6 @@ PROT Declaration::prot()
* Issue error if not.
*/
#if DMDV2
int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag)
{
VarDeclaration *v = isVarDeclaration();
@@ -161,14 +157,13 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int fl
}
return 1;
}
#endif
Dsymbol *Declaration::search(Loc loc, Identifier *ident, int flags)
{
Dsymbol *s = Dsymbol::search(loc, ident, flags);
if (!s && type)
{
s = type->toDsymbol(NULL);
s = type->toDsymbol(scope);
if (s)
s = s->search(loc, ident, flags);
}
@@ -359,9 +354,7 @@ void TypedefDeclaration::semantic(Scope *sc)
return;
}
sem = SemanticDone;
#if DMDV2
type = type->addStorageClass(storage_class);
#endif
Type *savedtype = type;
type = type->semantic(loc, sc);
if (sc->parent->isFuncDeclaration() && init)
@@ -379,6 +372,8 @@ void TypedefDeclaration::semantic(Scope *sc)
else if (sem == SemanticIn)
{
error("circular definition");
basetype = Type::terror;
errors = true;
}
}
@@ -387,6 +382,7 @@ void TypedefDeclaration::semantic2(Scope *sc)
//printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
if (sem == SemanticDone)
{ sem = Semantic2Done;
basetype->alignment(); // used to detect circular typedef declarations
if (init)
{
Initializer *savedinit = init;
@@ -508,11 +504,6 @@ void AliasDeclaration::semantic(Scope *sc)
}
this->inSemantic = true;
#if DMDV1 // don't really know why this is here
if (storage_class & STCconst)
error("cannot be const");
#endif
storage_class |= sc->stc & STCdeprecated;
protection = sc->protection;
userAttributes = sc->userAttributes;
@@ -545,14 +536,9 @@ void AliasDeclaration::semantic(Scope *sc)
s = NULL;
type = Type::terror;
}
if (s
#if DMDV2
&& ((s->getType() && type->equals(s->getType())) || s->isEnumMember())
#endif
)
if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()))
goto L2; // it's a symbolic alias
#if DMDV2
type = type->addStorageClass(storage_class);
if (storage_class & (STCref | STCnothrow | STCpure | STCdisable))
{ // For 'ref' to be attached to function types, and picked
@@ -563,7 +549,6 @@ void AliasDeclaration::semantic(Scope *sc)
sc = sc->pop();
}
else
#endif
type->resolve(loc, sc, &e, &t, &s);
if (s)
{
@@ -730,38 +715,18 @@ Dsymbol *AliasDeclaration::toAlias()
void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("alias ");
#if 0
if (hgs->hdrgen)
if (aliassym)
{
if (haliassym)
{
#if IN_LLVM
buf->writestring(haliassym->toChars());
buf->writestring(aliassym->toChars());
#else
haliassym->toCBuffer(buf, hgs);
aliassym->toCBuffer(buf, hgs);
#endif
buf->writeByte(' ');
buf->writestring(ident->toChars());
}
else
htype->toCBuffer(buf, ident, hgs);
buf->writeByte(' ');
buf->writestring(ident->toChars());
}
else
#endif
{
if (aliassym)
{
#if IN_LLVM
buf->writestring(aliassym->toChars());
#else
aliassym->toCBuffer(buf, hgs);
#endif
buf->writeByte(' ');
buf->writestring(ident->toChars());
}
else
type->toCBuffer(buf, ident, hgs);
}
type->toCBuffer(buf, ident, hgs);
buf->writeByte(';');
buf->writenl();
}
@@ -786,27 +751,19 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
this->loc = loc;
offset = 0;
noscope = 0;
#if DMDV2
isargptr = FALSE;
#endif
#if DMDV1
nestedref = 0;
#endif
isargptr = false;
alignment = 0;
ctorinit = 0;
aliassym = NULL;
onstack = 0;
canassign = 0;
lastVar = NULL;
ctfeAdrOnStack = -1;
#if DMDV2
rundtor = NULL;
edtor = NULL;
#endif
#if IN_LLVM
aggrIndex = 0;
nakedUse = false;
availableExternally = true; // assume this unless proven otherwise
#endif
}
@@ -873,7 +830,8 @@ void VarDeclaration::semantic(Scope *sc)
Scope *scx = NULL;
if (scope)
{ sc = scope;
{
sc = scope;
scx = sc;
scope = NULL;
}
@@ -894,17 +852,19 @@ void VarDeclaration::semantic(Scope *sc)
*/
int inferred = 0;
if (!type)
{ inuse++;
{
inuse++;
// Infering the type requires running semantic,
// so mark the scope as ctfe if required
bool needctfe = (storage_class & (STCmanifest | STCstatic));
bool needctfe = (storage_class & (STCmanifest | STCstatic)) != 0;
if (needctfe) sc = sc->startCTFE();
//printf("inferring type for %s with init %s\n", toChars(), init->toChars());
ArrayInitializer *ai = init->isArrayInitializer();
if (ai)
{ Expression *e;
{
Expression *e;
if (ai->isAssociativeArray())
e = ai->toAssocArrayLiteral();
else
@@ -931,7 +891,8 @@ void VarDeclaration::semantic(Scope *sc)
inferred = 1;
if (init->isArrayInitializer() && type->toBasetype()->ty == Tsarray)
{ // Prefer array literals to give a T[] type rather than a T[dim]
{
// Prefer array literals to give a T[] type rather than a T[dim]
type = type->toBasetype()->nextOf()->arrayOf();
}
@@ -942,7 +903,8 @@ void VarDeclaration::semantic(Scope *sc)
originalType = type->syntaxCopy();
}
else
{ if (!originalType)
{
if (!originalType)
originalType = type->syntaxCopy();
inuse++;
type = type->semantic(loc, sc);
@@ -966,7 +928,6 @@ void VarDeclaration::semantic(Scope *sc)
//printf("sc->stc = %x\n", sc->stc);
//printf("storage_class = x%x\n", storage_class);
#if DMDV2
// Safety checks
if (sc->func && !sc->intypeof)
{
@@ -994,10 +955,8 @@ void VarDeclaration::semantic(Scope *sc)
}
}
}
#endif
Dsymbol *parent = toParent();
FuncDeclaration *fd = parent->isFuncDeclaration();
Type *tb = type->toBasetype();
Type *tbn = tb->baseElemOf();
@@ -1014,13 +973,14 @@ void VarDeclaration::semantic(Scope *sc)
tb = type;
}
if (tb->ty == Tfunction)
{ error("cannot be declared to be a function");
{
error("cannot be declared to be a function");
type = Type::terror;
tb = type;
}
if (tb->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tb;
{
TypeStruct *ts = (TypeStruct *)tb;
if (!ts->sym->members)
{
error("no definition of struct %s", ts->toChars());
@@ -1030,13 +990,12 @@ void VarDeclaration::semantic(Scope *sc)
error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?");
if (tb->ty == Ttuple)
{ /* Instead, declare variables for each of the tuple elements
{
/* Instead, declare variables for each of the tuple elements
* and add those.
*/
TypeTuple *tt = (TypeTuple *)tb;
size_t nelems = Parameter::dim(tt->arguments);
Objects *exps = new Objects();
exps->setDim(nelems);
Expression *ie = (init && !init->isVoidInitializer()) ? init->toExpression() : NULL;
if (ie) ie = ie->semantic(sc);
@@ -1081,7 +1040,7 @@ void VarDeclaration::semantic(Scope *sc)
Identifier *id = Lexer::uniqueId("__tup");
ExpInitializer *ei = new ExpInitializer(e->loc, e);
VarDeclaration *v = new VarDeclaration(loc, NULL, id, ei);
v->storage_class = STCctfe | STCref | STCforeach;
v->storage_class = STCtemp | STCctfe | STCref | STCforeach;
VarExp *ve = new VarExp(loc, v);
ve->type = e->type;
@@ -1093,7 +1052,7 @@ void VarDeclaration::semantic(Scope *sc)
{
Lexpand2:
Expression *ee = (*exps)[u];
Parameter *arg = Parameter::getNth(tt->arguments, pos + u);
arg = Parameter::getNth(tt->arguments, pos + u);
arg->type = arg->type->semantic(loc, sc);
//printf("[%d+%d] exps->dim = %d, ", pos, u, exps->dim);
//printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars());
@@ -1133,12 +1092,15 @@ Lnomatch:
TupleExp *te = (TupleExp *)ie;
size_t tedim = te->exps->dim;
if (tedim != nelems)
{ ::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems);
{
::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems);
for (size_t u = tedim; u < nelems; u++) // fill dummy expression
te->exps->push(new ErrorExp());
}
}
Objects *exps = new Objects();
exps->setDim(nelems);
for (size_t i = 0; i < nelems; i++)
{
Parameter *arg = Parameter::getNth(tt->arguments, i);
@@ -1166,7 +1128,7 @@ Lnomatch:
ti = init ? init->syntaxCopy() : NULL;
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
v->storage_class |= storage_class;
v->storage_class |= STCtemp | storage_class;
if (arg->storageClass & STCparameter)
v->storage_class |= arg->storageClass;
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
@@ -1176,7 +1138,8 @@ Lnomatch:
// removed for LDC since TupleDeclaration::toObj already creates the fields;
// adding them to the scope again leads to duplicates
if (sc->scopesym)
{ //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
{
//printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars());
if (sc->scopesym->members)
sc->scopesym->members->push(v);
}
@@ -1247,14 +1210,12 @@ Lnomatch:
fprintf(global.stdmsg, "%s: %s.%s is %s field\n", p ? p : "", ad->toPrettyChars(), toChars(), s);
}
storage_class |= STCfield;
#if DMDV2
if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor ||
tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor)
{
if (!isThisDeclaration())
aad->noDefaultCtor = TRUE;
if (!isThisDeclaration() && !init)
aad->noDefaultCtor = true;
}
#endif
#else
if (storage_class & (STCconst | STCimmutable) && init)
{
@@ -1267,14 +1228,12 @@ Lnomatch:
else
{
storage_class |= STCfield;
#if DMDV2
if ((tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor) ||
(tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor))
{
if (!isThisDeclaration())
aad->noDefaultCtor = TRUE;
if (!isThisDeclaration() && !init)
aad->noDefaultCtor = true;
}
#endif
}
#endif
}
@@ -1308,7 +1267,6 @@ Lnomatch:
}
}
#if DMDV2
if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref &&
ident != Id::This)
{
@@ -1360,8 +1318,8 @@ Lnomatch:
error("default construction is disabled for type %s", type->toChars());
}
}
#endif
FuncDeclaration *fd = parent->isFuncDeclaration();
if (type->isscope() && !noscope)
{
if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd)
@@ -1416,7 +1374,8 @@ Lnomatch:
}
else if (type->ty == Tstruct &&
((TypeStruct *)type)->sym->zeroInit == 1)
{ /* If a struct is all zeros, as a special case
{
/* If a struct is all zeros, as a special case
* set it's initializer to the integer 0.
* In AssignExp::toElem(), we check for this and issue
* a memset() to initialize the struct.
@@ -1431,9 +1390,11 @@ Lnomatch:
goto Ldtor;
}
else if (type->ty == Ttypedef)
{ TypeTypedef *td = (TypeTypedef *)type;
{
TypeTypedef *td = (TypeTypedef *)type;
if (td->sym->init)
{ init = td->sym->init;
{
init = td->sym->init;
ExpInitializer *ie = init->isExpInitializer();
if (ie)
// Make copy so we can modify it
@@ -1455,22 +1416,16 @@ Lnomatch:
sc = sc->push();
sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref | STCdisable);
ArrayInitializer *ai = init->isArrayInitializer();
if (ai && tb->ty == Taarray)
{
Expression *e = ai->toAssocArrayLiteral();
init = new ExpInitializer(e->loc, e);
}
ExpInitializer *ei = init->isExpInitializer();
if (ei && isScope())
{
// See if initializer is a NewExp that can be allocated on the stack
if (ei->exp->op == TOKnew)
{ NewExp *ne = (NewExp *)ei->exp;
{
NewExp *ne = (NewExp *)ei->exp;
if (!(ne->newargs && ne->newargs->dim))
{ ne->onstack = 1;
{
ne->onstack = 1;
onstack = 1;
if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
onstack = 2;
@@ -1478,7 +1433,8 @@ Lnomatch:
}
// or a delegate that doesn't escape a reference to the function
else if (ei->exp->op == TOKfunction)
{ FuncDeclaration *f = ((FuncExp *)ei->exp)->fd;
{
FuncDeclaration *f = ((FuncExp *)ei->exp)->fd;
f->tookAddressOf--;
}
}
@@ -1495,14 +1451,20 @@ Lnomatch:
//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
if (!ei)
{
Expression *e = init->toExpression();
ArrayInitializer *ai = init->isArrayInitializer();
Expression *e;
if (ai && (tb->ty == Taarray || tb->ty == Tstruct && ai->isAssociativeArray()))
e = ai->toAssocArrayLiteral();
else
e = init->toExpression();
if (!e)
{
// Run semantic, but don't need to interpret
init = init->semantic(sc, type, INITnointerpret);
e = init->toExpression();
if (!e)
{ error("is not a static and cannot have static initializer");
{
error("is not a static and cannot have static initializer");
return;
}
}
@@ -1511,150 +1473,6 @@ Lnomatch:
}
Expression *e1 = new VarExp(loc, this);
Type *t = type->toBasetype();
if (ei && !inferred)
ei->exp = ei->exp->inferType(t);
Linit2:
if (t->ty == Tsarray && !(storage_class & (STCref | STCout)))
{
ei->exp = ei->exp->semantic(sc);
if (!ei->exp->implicitConvTo(type))
{
dinteger_t dim = ((TypeSArray *)t)->dim->toInteger();
// If multidimensional static array, treat as one large array
while (1)
{
t = t->nextOf()->toBasetype();
if (t->ty != Tsarray)
break;
dim *= ((TypeSArray *)t)->dim->toInteger();
e1->type = TypeSArray::makeType(Loc(), t->nextOf(), dim);
}
}
e1 = new SliceExp(loc, e1, NULL, NULL);
}
else if (t->ty == Tstruct)
{
ei->exp = ei->exp->semantic(sc);
ei->exp = resolveProperties(sc, ei->exp);
StructDeclaration *sd = ((TypeStruct *)t)->sym;
#if DMDV2
Expression** pinit = &ei->exp;
while ((*pinit)->op == TOKcomma)
{
pinit = &((CommaExp *)*pinit)->e2;
}
/* Look to see if initializer is a call to the constructor
*/
if (sd->ctor && // there are constructors
(*pinit)->type->ty == Tstruct && // rvalue is the same struct
((TypeStruct *)(*pinit)->type)->sym == sd &&
(*pinit)->op == TOKcall)
{
/* Look for form of constructor call which is:
* *__ctmp.ctor(arguments...)
*/
if ((*pinit)->type->implicitConvTo(t))
{ CallExp *ce = (CallExp *)(*pinit);
if (ce->e1->op == TOKdotvar)
{ DotVarExp *dve = (DotVarExp *)ce->e1;
if (dve->var->isCtorDeclaration())
{ /* It's a constructor call, currently constructing
* a temporary __ctmp.
*/
/* Before calling the constructor, initialize
* variable with a bit copy of the default
* initializer
*/
/* Remove ref if this declaration is ref binding.
* ref Type __self = (__ctmp = 0, __ctmp).this(...);
* -> Type __self = (__self = 0, __self.this(...));
*/
storage_class &= ~(STCref | STCforeach | STCparameter);
Expression *e = new VarExp(loc, this);
if (sd->zeroInit == 1)
{
e = new ConstructExp(loc, e, new IntegerExp(loc, 0, Type::tint32));
}
else if (sd->isNested())
{
e = new AssignExp(loc, e, t->defaultInitLiteral(loc));
e->op = TOKblit;
}
else
{
e = new AssignExp(loc, e, t->defaultInit(loc));
e->op = TOKblit;
}
e->type = t;
/* Replace __ctmp being constructed with e1.
* We need to copy constructor call expression,
* because it may be used in other place.
*/
DotVarExp *dvx = (DotVarExp *)dve->copy();
dvx->e1 = e1;
CallExp *cx = (CallExp *)ce->copy();
cx->e1 = dvx;
(*pinit) = new CommaExp(loc, e, cx);
(*pinit) = (*pinit)->semantic(sc);
goto Ldtor;
}
}
}
}
/* Look for ((S tmp = S()),tmp) and replace it with just S()
*/
Expression *e2 = ei->exp->isTemp();
if (e2)
{
ei->exp = e2;
goto Linit2;
}
#endif
if (!ei->exp->implicitConvTo(type))
{
Type *ti = ei->exp->type->toBasetype();
// Look for constructor first
if (sd->ctor &&
/* Initializing with the same type is done differently
*/
!(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc)))
{
// Rewrite as e1.ctor(arguments)
Expression *ector = new DotIdExp(loc, e1, Id::ctor);
ei->exp = new CallExp(loc, ector, ei->exp);
/* Before calling the constructor, initialize
* variable with a bit copy of the default
* initializer
*/
Expression *e = new AssignExp(loc, e1, t->defaultInit(loc));
e->op = TOKblit;
e->type = t;
ei->exp = new CommaExp(loc, e, ei->exp);
}
else
/* Look for static opCall
* See bugzilla 2702 for more discussion
*/
// Don't cast away invariant or mutability in initializer
if (search_function(sd, Id::call) &&
/* Initializing with the same type is done differently
*/
!(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc)))
{ // Rewrite as e1.call(arguments)
Expression *e = typeDotIdExp(ei->exp->loc, t, Id::call);
ei->exp = new CallExp(loc, e, ei->exp);
}
}
}
ei->exp = new AssignExp(loc, e1, ei->exp);
ei->exp->op = op;
canassign++;
@@ -1685,7 +1503,6 @@ Lnomatch:
{
unsigned errors = global.errors;
inuse++;
#if DMDV2
if (ei)
{
Expression *exp = ei->exp->syntaxCopy();
@@ -1696,7 +1513,7 @@ Lnomatch:
exp = resolveProperties(sc, exp);
if (needctfe) sc = sc->endCTFE();
Type *tb = type->toBasetype();
Type *tb2 = type->toBasetype();
Type *ti = exp->type->toBasetype();
/* The problem is the following code:
@@ -1717,16 +1534,15 @@ Lnomatch:
* (which implies a postblit)
*/
if (sd->cpctor && // there is a copy constructor
tb->toDsymbol(NULL) == sd) // exp is the same struct
tb2->toDsymbol(NULL) == sd) // exp is the same struct
{
// The only allowable initializer is a (non-copy) constructor
if (exp->isLvalue())
error("of type struct %s uses this(this), which is not allowed in static initialization", tb->toChars());
error("of type struct %s uses this(this), which is not allowed in static initialization", tb2->toChars());
}
}
ei->exp = exp;
}
#endif
init = init->semantic(sc, type, INITinterpret);
inuse--;
if (global.errors > errors)
@@ -1927,7 +1743,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
}
unsigned memsize = t->size(loc); // size of member
unsigned memsize = (unsigned)t->size(loc); // size of member
unsigned memalignsize = Target::fieldalign(t); // size of member for alignment purposes
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment,
@@ -1978,12 +1794,10 @@ void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring(ident->toChars());
if (init)
{ buf->writestring(" = ");
#if DMDV2
ExpInitializer *ie = init->isExpInitializer();
if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
else
#endif
init->toCBuffer(buf, hgs);
}
buf->writeByte(';');
@@ -2106,7 +1920,8 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
if (i == fdv->closureVars.dim)
{
fdv->closureVars.push(this);
if (!sc->intypeof && !(sc->flags & SCOPEcompile))
fdv->closureVars.push(this);
break;
}
if (fdv->closureVars[i] == this)
@@ -2440,7 +2255,6 @@ char *TypeInfoDeclaration::toChars()
/***************************** TypeInfoConstDeclaration **********************/
#if DMDV2
TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
: TypeInfoDeclaration(tinfo, 0)
{
@@ -2450,11 +2264,9 @@ TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
}
type = Type::typeinfoconst->type;
}
#endif
/***************************** TypeInfoInvariantDeclaration **********************/
#if DMDV2
TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
: TypeInfoDeclaration(tinfo, 0)
{
@@ -2464,11 +2276,9 @@ TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
}
type = Type::typeinfoinvariant->type;
}
#endif
/***************************** TypeInfoSharedDeclaration **********************/
#if DMDV2
TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo)
: TypeInfoDeclaration(tinfo, 0)
{
@@ -2478,11 +2288,9 @@ TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo)
}
type = Type::typeinfoshared->type;
}
#endif
/***************************** TypeInfoWildDeclaration **********************/
#if DMDV2
TypeInfoWildDeclaration::TypeInfoWildDeclaration(Type *tinfo)
: TypeInfoDeclaration(tinfo, 0)
{
@@ -2492,7 +2300,6 @@ TypeInfoWildDeclaration::TypeInfoWildDeclaration(Type *tinfo)
}
type = Type::typeinfowild->type;
}
#endif
/***************************** TypeInfoStructDeclaration **********************/
@@ -2665,4 +2472,4 @@ Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
assert(0); // should never be produced by syntax
return NULL;
}
+14 -36
View File
@@ -91,16 +91,16 @@ enum PURE;
#define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild)
#define STC_FUNCATTR (STCref | STCnothrow | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem)
#define STCproperty 0x100000000LL
#define STCsafe 0x200000000LL
#define STCtrusted 0x400000000LL
#define STCsystem 0x800000000LL
#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static
#define STCdisable 0x2000000000LL // for functions that are not callable
#define STCresult 0x4000000000LL // for result variables passed to out contracts
#define STCproperty 0x100000000LL
#define STCsafe 0x200000000LL
#define STCtrusted 0x400000000LL
#define STCsystem 0x800000000LL
#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static
#define STCdisable 0x2000000000LL // for functions that are not callable
#define STCresult 0x4000000000LL // for result variables passed to out contracts
#define STCnodefaultctor 0x8000000000LL // must be set inside constructor
#define STCtemp 0x10000000000LL // temporary variable introduced by inlining
// and used only in backend process, so it's rvalue
#define STCtemp 0x10000000000LL // temporary variable
#define STCrvalue 0x20000000000LL // force rvalue for variables
const StorageClass STCStorageClass = (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal |
STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias |
@@ -288,18 +288,15 @@ public:
Initializer *init;
unsigned offset;
bool noscope; // no auto semantics
#if DMDV2
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
bool isargptr; // if parameter that _argptr points to
#else
int nestedref; // referenced by a lexically nested function
#endif
structalign_t alignment;
bool ctorinit; // it has been initialized in a ctor
short onstack; // 1: it has been allocated on the stack
// 2: on stack, run destructor anyway
int canassign; // it can be assigned to
Dsymbol *aliassym; // if redone as alias to another symbol
VarDeclaration *lastVar; // Linked list of variables for goto-skips-init detection
// When interpreting, these point to the value (NULL if value not determinable)
// The index of this variable on the CTFE stack, -1 if not allocated
@@ -311,12 +308,10 @@ public:
void setValueWithoutChecking(Expression *newval);
void setValue(Expression *newval);
#if DMDV2
VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see
// if the destructor should be run. Used to prevent
// dtor calls on postblitted vars
Expression *edtor; // if !=NULL, does the destruction of the variable
#endif
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
Dsymbol *syntaxCopy(Dsymbol *);
@@ -336,10 +331,8 @@ public:
bool isThreadlocal();
bool isCTFE();
bool hasPointers();
#if DMDV2
bool canTakeAddressOf();
bool needsAutoDtor();
#endif
Expression *callScopeDtor(Scope *sc);
ExpInitializer *getExpInitializer();
Expression *getConstInitializer(bool needFullType = true);
@@ -616,7 +609,6 @@ public:
#endif
};
#if DMDV2
class TypeInfoConstDeclaration : public TypeInfoDeclaration
{
public:
@@ -686,7 +678,6 @@ public:
void llvmDefine();
#endif
};
#endif
/**************************************************************/
@@ -706,7 +697,6 @@ enum ILS
};
/**************************************************************/
#if DMDV2
enum BUILTIN
{
@@ -733,9 +723,6 @@ enum BUILTIN
Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments);
#else
enum BUILTIN { };
#endif
class FuncDeclaration : public Declaration
{
@@ -812,8 +799,8 @@ public:
#endif
ReturnStatements *returns;
GotoStatements *gotos; // Gotos with forward references
#if DMDV2
BUILTIN builtin; // set if this is a known, builtin
// function we can evaluate at compile
// time
@@ -834,9 +821,6 @@ public:
#define FUNCFLAGpurityInprocess 1 // working on determining purity
#define FUNCFLAGsafetyInprocess 2 // working on determining safety
#define FUNCFLAGnothrowInprocess 4 // working on determining nothrow
#else
int nestedFrameRef; // !=0 if nested variables referenced
#endif
FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type);
Dsymbol *syntaxCopy(Dsymbol *);
@@ -897,7 +881,7 @@ public:
void ctfeCompile();
void inlineScan();
int canInline(int hasthis, int hdrscan, int statementsToo);
Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps);
Expression *expandInline(InlineScanState *iss, Expression *eret, Expression *ethis, Expressions *arguments, Statement **ps);
const char *kind();
void toDocBuffer(OutBuffer *buf, Scope *sc);
FuncDeclaration *isUnique();
@@ -960,13 +944,11 @@ public:
#endif
};
#if DMDV2
FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
Objects *tiargs,
Type *tthis,
Expressions *arguments,
int flags = 0);
#endif
class FuncAliasDeclaration : public FuncDeclaration
{
@@ -1001,6 +983,7 @@ public:
FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
const char *kind();
const char *toPrettyChars();
#if IN_LLVM
// If this is only used as alias parameter to a template instantiation,
@@ -1028,7 +1011,6 @@ public:
CtorDeclaration *isCtorDeclaration() { return this; }
};
#if DMDV2
class PostBlitDeclaration : public FuncDeclaration
{
public:
@@ -1045,7 +1027,6 @@ public:
PostBlitDeclaration *isPostBlitDeclaration() { return this; }
};
#endif
class DtorDeclaration : public FuncDeclaration
{
@@ -1084,7 +1065,6 @@ public:
StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
};
#if DMDV2
class SharedStaticCtorDeclaration : public StaticCtorDeclaration
{
public:
@@ -1094,7 +1074,6 @@ public:
SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; }
};
#endif
class StaticDtorDeclaration : public FuncDeclaration
{
@@ -1116,7 +1095,6 @@ public:
StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
};
#if DMDV2
class SharedStaticDtorDeclaration : public StaticDtorDeclaration
{
public:
@@ -1126,7 +1104,6 @@ public:
SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; }
};
#endif
class InvariantDeclaration : public FuncDeclaration
{
@@ -1155,6 +1132,7 @@ public:
bool addPreInvariant();
bool addPostInvariant();
void emitComment(Scope *sc);
void inlineScan();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
+77 -91
View File
@@ -47,10 +47,10 @@ struct Escape
class Section
{
public:
utf8_t *name;
const utf8_t *name;
size_t namelen;
utf8_t *body;
const utf8_t *body;
size_t bodylen;
int nooutput;
@@ -86,19 +86,19 @@ struct DocComment
summary(NULL), copyright(NULL), macros(NULL), pmacrotable(NULL), pescapetable(NULL)
{ }
static DocComment *parse(Scope *sc, Dsymbol *s, utf8_t *comment);
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, utf8_t *m, size_t mlen);
static void parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t textlen);
static DocComment *parse(Scope *sc, Dsymbol *s, const utf8_t *comment);
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, const utf8_t *m, size_t mlen);
static void parseEscapes(Escape **pescapetable, const utf8_t *textstart, size_t textlen);
void parseSections(utf8_t *comment);
void parseSections(const utf8_t *comment);
void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf);
};
int cmp(const char *stringz, void *s, size_t slen);
int icmp(const char *stringz, void *s, size_t slen);
int isDitto(utf8_t *comment);
utf8_t *skipwhitespace(utf8_t *p);
int cmp(const char *stringz, const void *s, size_t slen);
int icmp(const char *stringz, const void *s, size_t slen);
int isDitto(const utf8_t *comment);
const utf8_t *skipwhitespace(const utf8_t *p);
size_t skiptoident(OutBuffer *buf, size_t i);
size_t skippastident(OutBuffer *buf, size_t i);
size_t skippastURL(OutBuffer *buf, size_t i);
@@ -106,13 +106,13 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool anchor = true);
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
TypeFunction *isTypeFunction(Dsymbol *s);
Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len);
TemplateParameter *isTemplateParameter(Dsymbol *s, utf8_t *p, size_t len);
Parameter *isFunctionParameter(Dsymbol *s, const utf8_t *p, size_t len);
TemplateParameter *isTemplateParameter(Dsymbol *s, const utf8_t *p, size_t len);
int isIdStart(utf8_t *p);
int isIdTail(utf8_t *p);
int isIndentWS(utf8_t *p);
int utfStride(utf8_t *p);
int isIdStart(const utf8_t *p);
int isIdTail(const utf8_t *p);
int isIndentWS(const utf8_t *p);
int utfStride(const utf8_t *p);
static const char ddoc_default[] = "\
DDOC = <html><head>\n\
@@ -249,7 +249,7 @@ void Module::gendocfile()
mbuf.write(file.buffer, file.len);
}
}
DocComment::parseMacros(&escapetable, &macrotable, mbuf.data, mbuf.offset);
DocComment::parseMacros(&escapetable, &macrotable, (utf8_t *)mbuf.data, mbuf.offset);
Scope *sc = Scope::createGlobal(this); // create root scope
sc->docbuf = &buf;
@@ -305,7 +305,7 @@ void Module::gendocfile()
}
//printf("BODY= '%.*s'\n", buf.offset, buf.data);
Macro::define(&macrotable, (utf8_t *)"BODY", 4, buf.data, buf.offset);
Macro::define(&macrotable, (utf8_t *)"BODY", 4, (utf8_t *)buf.data, buf.offset);
OutBuffer buf2;
buf2.writestring("$(DDOC)\n");
@@ -319,7 +319,7 @@ void Module::gendocfile()
{
buf.setsize(0);
buf.reserve(buf2.offset);
utf8_t *p = buf2.data;
utf8_t *p = (utf8_t *)buf2.data;
for (size_t j = 0; j < buf2.offset; j++)
{
utf8_t c = p[j];
@@ -552,7 +552,7 @@ void emitUnittestComment(Scope *sc, Dsymbol *s, size_t ofs)
continue;
// Strip whitespaces to avoid showing empty summary
utf8_t *c = utd->comment;
const utf8_t *c = utd->comment;
while (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r') ++c;
OutBuffer codebuf;
@@ -665,9 +665,7 @@ void emitProtection(OutBuffer *buf, PROT prot)
void Dsymbol::emitComment(Scope *sc) { }
void InvariantDeclaration::emitComment(Scope *sc) { }
void UnitTestDeclaration::emitComment(Scope *sc) { }
#if DMDV2
void PostBlitDeclaration::emitComment(Scope *sc) { }
#endif
void DtorDeclaration::emitComment(Scope *sc) { }
void StaticCtorDeclaration::emitComment(Scope *sc) { }
void StaticDtorDeclaration::emitComment(Scope *sc) { }
@@ -746,7 +744,7 @@ void TemplateDeclaration::emitComment(Scope *sc)
if (prot() == PROTprivate)
return;
utf8_t *com = comment;
const utf8_t *com = comment;
int hasmembers = 1;
Dsymbol *ss = this;
@@ -900,10 +898,8 @@ void prefix(OutBuffer *buf, Dsymbol *s)
{
if (d->isConst())
buf->writestring("const ");
#if DMDV2
if (d->isImmutable())
buf->writestring("immutable ");
#endif
if (d->isSynchronized())
buf->writestring("synchronized ");
}
@@ -1081,17 +1077,6 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
}
}
#if DMDV1
void CtorDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
HdrGenState hgs;
buf->writestring("this");
Parameter::argsToCBuffer(buf, &hgs, arguments, varargs);
buf->writestring(";\n");
}
#endif
void AggregateDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
if (ident)
@@ -1210,7 +1195,7 @@ void EnumMember::toDocBuffer(OutBuffer *buf, Scope *sc)
/********************************* DocComment *********************************/
DocComment *DocComment::parse(Scope *sc, Dsymbol *s, utf8_t *comment)
DocComment *DocComment::parse(Scope *sc, Dsymbol *s, const utf8_t *comment)
{
//printf("parse(%s): '%s'\n", s->toChars(), comment);
if (sc->lastdc && isDitto(comment))
@@ -1247,21 +1232,22 @@ DocComment *DocComment::parse(Scope *sc, Dsymbol *s, utf8_t *comment)
* then (*pcomment)[0 .. idlen] is the identifier.
*/
void DocComment::parseSections(utf8_t *comment)
{ utf8_t *p;
utf8_t *pstart;
utf8_t *pend;
utf8_t *idstart;
void DocComment::parseSections(const utf8_t *comment)
{
const utf8_t *p;
const utf8_t *pstart;
const utf8_t *pend;
const utf8_t *idstart;
size_t idlen;
utf8_t *name = NULL;
const utf8_t *name = NULL;
size_t namelen = 0;
//printf("parseSections('%s')\n", comment);
p = comment;
while (*p)
{
utf8_t *pstart0 = p;
const utf8_t *pstart0 = p;
p = skipwhitespace(p);
pstart = p;
pend = p;
@@ -1296,7 +1282,7 @@ void DocComment::parseSections(utf8_t *comment)
if (!inCode && isIdStart(p))
{
utf8_t *q = p + utfStride(p);
const utf8_t *q = p + utfStride(p);
while (isIdTail(q))
q += utfStride(q);
if (*q == ':') // identifier: ends it
@@ -1451,17 +1437,17 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
{
utf8_t *p = body;
const utf8_t *p = body;
size_t len = bodylen;
utf8_t *pend = p + len;
const utf8_t *pend = p + len;
utf8_t *tempstart;
const utf8_t *tempstart;
size_t templen;
utf8_t *namestart;
const utf8_t *namestart;
size_t namelen = 0; // !=0 if line continuation
utf8_t *textstart;
const utf8_t *textstart;
size_t textlen;
size_t o, paramcount = 0;
@@ -1606,19 +1592,19 @@ void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
* name2 = value2
*/
void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, utf8_t *m, size_t mlen)
void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, const utf8_t *m, size_t mlen)
{
utf8_t *p = m;
const utf8_t *p = m;
size_t len = mlen;
utf8_t *pend = p + len;
const utf8_t *pend = p + len;
utf8_t *tempstart;
const utf8_t *tempstart;
size_t templen;
utf8_t *namestart;
const utf8_t *namestart;
size_t namelen = 0; // !=0 if line continuation
utf8_t *textstart;
const utf8_t *textstart;
size_t textlen;
while (p < pend)
@@ -1731,7 +1717,7 @@ Ldone:
* by whitespace and/or commas.
*/
void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t textlen)
void DocComment::parseEscapes(Escape **pescapetable, const utf8_t *textstart, size_t textlen)
{ Escape *escapetable = *pescapetable;
if (!escapetable)
@@ -1740,8 +1726,8 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t
*pescapetable = escapetable;
}
//printf("parseEscapes('%.*s') pescapetable = %p\n", textlen, textstart, pescapetable);
utf8_t *p = textstart;
utf8_t *pend = p + textlen;
const utf8_t *p = textstart;
const utf8_t *pend = p + textlen;
while (1)
{
@@ -1757,7 +1743,7 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t
return;
utf8_t c = p[1];
p += 3;
utf8_t *start = p;
const utf8_t *start = p;
while (1)
{
if (p >= pend)
@@ -1781,7 +1767,7 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t
* Return < 0, ==0, > 0
*/
int cmp(const char *stringz, void *s, size_t slen)
int cmp(const char *stringz, const void *s, size_t slen)
{
size_t len1 = strlen(stringz);
@@ -1790,7 +1776,7 @@ int cmp(const char *stringz, void *s, size_t slen)
return memcmp(stringz, s, slen);
}
int icmp(const char *stringz, void *s, size_t slen)
int icmp(const char *stringz, const void *s, size_t slen)
{
size_t len1 = strlen(stringz);
@@ -1803,13 +1789,13 @@ int icmp(const char *stringz, void *s, size_t slen)
* Return !=0 if comment consists entirely of "ditto".
*/
int isDitto(utf8_t *comment)
int isDitto(const utf8_t *comment)
{
if (comment)
{
utf8_t *p = skipwhitespace(comment);
const utf8_t *p = skipwhitespace(comment);
if (Port::memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
if (Port::memicmp((const char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
return 1;
}
return 0;
@@ -1819,7 +1805,7 @@ int isDitto(utf8_t *comment)
* Skip white space.
*/
utf8_t *skipwhitespace(utf8_t *p)
const utf8_t *skipwhitespace(const utf8_t *p)
{
for (; 1; p++)
{ switch (*p)
@@ -1903,7 +1889,7 @@ size_t skippastident(OutBuffer *buf, size_t i)
size_t skippastURL(OutBuffer *buf, size_t i)
{ size_t length = buf->offset - i;
utf8_t *p = &buf->data[i];
utf8_t *p = (utf8_t *)&buf->data[i];
size_t j;
unsigned sawdot = 0;
@@ -1991,7 +1977,7 @@ TypeFunction *isTypeFunction(Dsymbol *s)
/****************************************************
*/
Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len)
Parameter *isFunctionParameter(Dsymbol *s, const utf8_t *p, size_t len)
{
TypeFunction *tf = isTypeFunction(s);
if (tf && tf->parameters)
@@ -2011,7 +1997,7 @@ Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len)
/****************************************************
*/
TemplateParameter *isTemplateParameter(Dsymbol *s, utf8_t *p, size_t len)
TemplateParameter *isTemplateParameter(Dsymbol *s, const utf8_t *p, size_t len)
{
TemplateDeclaration *td = s->isTemplateDeclaration();
if (td && td->origParameters)
@@ -2062,7 +2048,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
if (!sc->module->isDocFile &&
!inCode && i == iLineStart && i + 1 < buf->offset) // if "\n\n"
{
static char blankline[] = "$(DDOC_BLANKLINE)\n";
static const char blankline[] = "$(DDOC_BLANKLINE)\n";
i = buf->insert(i, blankline, strlen(blankline));
}
@@ -2074,7 +2060,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
leadingBlank = 0;
if (inCode)
break;
p = &buf->data[i];
p = (utf8_t *)&buf->data[i];
se = sc->module->escapetable->escapeChar('<');
if (se && strcmp(se, "&lt;") == 0)
@@ -2148,7 +2134,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
leadingBlank = 0;
if (inCode)
break;
p = &buf->data[i];
p = (utf8_t *)&buf->data[i];
if (p[1] == '#' || isalpha(p[1]))
break; // already a character entity
// Replace '&' with '&amp;' character entity
@@ -2220,8 +2206,8 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
// Remove leading indentations from all lines
bool lineStart = true;
utf8_t *endp = codebuf.data + codebuf.offset;
for (utf8_t *p = codebuf.data; p < endp; )
utf8_t *endp = (utf8_t *)codebuf.data + codebuf.offset;
for (p = (utf8_t *)codebuf.data; p < endp; )
{
if (lineStart)
{
@@ -2229,11 +2215,11 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
utf8_t *q = p;
while (j-- > 0 && q < endp && isIndentWS(q))
++q;
codebuf.remove(p - codebuf.data, q - p);
assert(codebuf.data <= p);
assert(p < codebuf.data + codebuf.offset);
codebuf.remove(p - (utf8_t *)codebuf.data, q - p);
assert((utf8_t *)codebuf.data <= p);
assert(p < (utf8_t *)codebuf.data + codebuf.offset);
lineStart = false;
endp = codebuf.data + codebuf.offset; // update
endp = (utf8_t *)codebuf.data + codebuf.offset; // update
continue;
}
if (*p == '\n')
@@ -2248,7 +2234,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
i -= 2; // in next loop, c should be '\n'
}
else
{ static char pre[] = "$(D_CODE \n";
{ static const char pre[] = "$(D_CODE \n";
inCode = 1;
codeIndent = istart - iLineStart; // save indent count
@@ -2263,7 +2249,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
default:
leadingBlank = 0;
if (!sc->module->isDocFile &&
!inCode && isIdStart(&buf->data[i]))
!inCode && isIdStart((utf8_t *)&buf->data[i]))
{
size_t j = skippastident(buf, i);
if (j > i)
@@ -2286,14 +2272,14 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1;
break;
}
else if (isKeyword(buf->data + i, j - i))
else if (isKeyword((utf8_t *)buf->data + i, j - i))
{
i = buf->bracket(i, "$(DDOC_KEYWORD ", j, ")") - 1;
break;
}
else
{
if (f && isFunctionParameter(f, buf->data + i, j - i))
if (f && isFunctionParameter(f, (utf8_t *)buf->data + i, j - i))
{
//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
@@ -2342,7 +2328,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
i = buf->insert(i, se, len);
i--; // point to ';'
}
else if (isIdStart(&buf->data[i]))
else if (isIdStart((utf8_t *)&buf->data[i]))
{
size_t j = skippastident(buf, i);
if (j > i)
@@ -2354,7 +2340,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
}
else if (f)
{
if (isFunctionParameter(f, buf->data + i, j - i))
if (isFunctionParameter(f, (utf8_t *)buf->data + i, j - i))
{
//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
@@ -2370,7 +2356,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
/****************************************
*/
void highlightCode3(Scope *sc, OutBuffer *buf, utf8_t *p, utf8_t *pend)
void highlightCode3(Scope *sc, OutBuffer *buf, const utf8_t *p, const utf8_t *pend)
{
for (; p < pend; p++)
{ const char *s = sc->module->escapetable->escapeChar(*p);
@@ -2391,10 +2377,10 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
const char *sid = s->ident->toChars();
FuncDeclaration *f = s->isFuncDeclaration();
unsigned errorsave = global.errors;
Lexer lex(NULL, buf->data, 0, buf->offset - 1, 0, 1);
Lexer lex(NULL, (utf8_t *)buf->data, 0, buf->offset - 1, 0, 1);
Token tok;
OutBuffer res;
utf8_t *lastp = buf->data;
const utf8_t *lastp = (utf8_t *)buf->data;
const char *highlight;
if (s->isModule() && ((Module *)s)->isDocFile)
@@ -2496,7 +2482,7 @@ const char *Escape::escapeChar(unsigned c)
* Determine if p points to the start of an identifier.
*/
int isIdStart(utf8_t *p)
int isIdStart(const utf8_t *p)
{
unsigned c = *p;
if (isalpha(c) || c == '_')
@@ -2515,7 +2501,7 @@ int isIdStart(utf8_t *p)
* Determine if p points to the rest of an identifier.
*/
int isIdTail(utf8_t *p)
int isIdTail(const utf8_t *p)
{
unsigned c = *p;
if (isalnum(c) || c == '_')
@@ -2534,7 +2520,7 @@ int isIdTail(utf8_t *p)
* Determine if p points to the indentation space.
*/
int isIndentWS(utf8_t *p)
int isIndentWS(const utf8_t *p)
{
return (*p == ' ') || (*p == '\t');
}
@@ -2543,7 +2529,7 @@ int isIndentWS(utf8_t *p)
* Return number of bytes in UTF character.
*/
int utfStride(utf8_t *p)
int utfStride(const utf8_t *p)
{
unsigned c = *p;
if (c < 0x80)
+30 -33
View File
@@ -199,7 +199,7 @@ bool Dsymbol::hasPointers()
bool Dsymbol::hasStaticCtorOrDtor()
{
//printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
return FALSE;
return false;
}
void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
@@ -466,24 +466,23 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
//printf("\ttemplate instance id\n");
Dsymbol *st = (Dsymbol *)id;
TemplateInstance *ti = st->isTemplateInstance();
Identifier *id = ti->name;
sm = s->search(loc, id, 0);
sm = s->search(loc, ti->name, 0);
if (!sm)
{
sm = s->search_correct(id);
sm = s->search_correct(ti->name);
if (sm)
error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?",
id->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars());
ti->name->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars());
else
error("template identifier '%s' is not a member of '%s %s'",
id->toChars(), s->kind(), s->toChars());
ti->name->toChars(), s->kind(), s->toChars());
return NULL;
}
sm = sm->toAlias();
TemplateDeclaration *td = sm->isTemplateDeclaration();
if (!td)
{
error("%s is not a template, it is a %s", id->toChars(), sm->kind());
error("%s is not a template, it is a %s", ti->name->toChars(), sm->kind());
return NULL;
}
ti->tempdecl = td;
@@ -568,7 +567,6 @@ bool Dsymbol::isDeprecated()
return false;
}
#if DMDV2
bool Dsymbol::isOverloadable()
{
return false;
@@ -578,7 +576,6 @@ bool Dsymbol::hasOverloads()
{
return false;
}
#endif
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
{
@@ -806,24 +803,21 @@ Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a)
* Ignore NULL comments.
*/
void Dsymbol::addComment(utf8_t *comment)
void Dsymbol::addComment(const utf8_t *comment)
{
//if (comment)
//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
if (!this->comment)
this->comment = comment;
#if 1
else if (comment && strcmp((char *)comment, (char *)this->comment) != 0)
{ // Concatenate the two
this->comment = Lexer::combineComments(this->comment, comment);
}
#endif
}
/********************************* OverloadSet ****************************/
#if DMDV2
OverloadSet::OverloadSet(Identifier *ident)
: Dsymbol(ident)
{
@@ -838,7 +832,6 @@ const char *OverloadSet::kind()
{
return "overloadset";
}
#endif
/********************************* ScopeDsymbol ****************************/
@@ -1028,7 +1021,7 @@ void ScopeDsymbol::importScope(Dsymbol *s, PROT protection)
}
}
imports->push(s);
prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
prots = (PROT *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
prots[imports->dim - 1] = protection;
}
}
@@ -1115,17 +1108,16 @@ bool ScopeDsymbol::hasStaticCtorOrDtor()
{ Dsymbol *member = (*members)[i];
if (member->hasStaticCtorOrDtor())
return TRUE;
return true;
}
}
return FALSE;
return false;
}
/***************************************
* Determine number of Dsymbols, folding in AttribDeclaration members.
*/
#if DMDV2
static int dimDg(void *ctx, size_t n, Dsymbol *)
{
++*(size_t *)ctx;
@@ -1138,7 +1130,6 @@ size_t ScopeDsymbol::dim(Dsymbols *members)
foreach(NULL, members, &dimDg, &n);
return n;
}
#endif
/***************************************
* Get nth Dsymbol, folding in AttribDeclaration members.
@@ -1148,7 +1139,6 @@ size_t ScopeDsymbol::dim(Dsymbols *members)
* of Dsymbols
*/
#if DMDV2
struct GetNthSymbolCtx
{
size_t nth;
@@ -1171,7 +1161,6 @@ Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn)
int res = foreach(NULL, members, &getNthSymbolDg, &ctx);
return res ? ctx.sym : NULL;
}
#endif
/***************************************
* Expands attribute declarations in members in depth first
@@ -1182,7 +1171,6 @@ Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn)
* calculating dim and calling N times getNth.
*/
#if DMDV2
int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *ctx, size_t *pn)
{
assert(dg);
@@ -1213,7 +1201,6 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg
*pn = n; // update index
return result;
}
#endif
/*******************************************
* Look for member of the form:
@@ -1221,7 +1208,6 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg
* Returns NULL if not found
*/
#if DMDV2
FuncDeclaration *ScopeDsymbol::findGetMembers()
{
Dsymbol *s = search_function(this, Id::getmembers);
@@ -1249,7 +1235,6 @@ FuncDeclaration *ScopeDsymbol::findGetMembers()
return fdx;
}
#endif
/****************************** WithScopeSymbol ******************************/
@@ -1267,11 +1252,22 @@ Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
Expression *eold = NULL;
for (Expression *e = withstate->exp; e != eold; e = resolveAliasThis(scope, e))
{
Type *t = e->type->toBasetype();
if (t->ty == Taarray)
s = ((TypeAArray *)t)->getImpl();
if (e->op == TOKimport)
{
s = ((ScopeExp *)e)->sds;
}
else if (e->op == TOKtype)
{
s = e->type->toDsymbol(NULL);
}
else
s = t->toDsymbol(NULL);
{
Type *t = e->type->toBasetype();
if (t->ty == Taarray)
s = ((TypeAArray *)t)->getImpl();
else
s = t->toDsymbol(NULL);
}
if (s)
{
s = s->search(loc, ident, 0);
@@ -1328,7 +1324,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t);
v->init = new ExpInitializer(Loc(), e);
v->storage_class |= STCstatic | STCconst;
v->storage_class |= STCtemp | STCstatic | STCconst;
v->semantic(sc);
return v;
}
@@ -1339,7 +1335,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t);
v->init = new ExpInitializer(Loc(), e);
v->storage_class |= STCstatic | STCconst;
v->storage_class |= STCtemp | STCstatic | STCconst;
v->semantic(sc);
return v;
}
@@ -1404,7 +1400,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
*/
Expression *e = new IntegerExp(Loc(), ((TupleExp *)ce)->exps->dim, Type::tsize_t);
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(Loc(), e));
v->storage_class |= STCstatic | STCconst;
v->storage_class |= STCtemp | STCstatic | STCconst;
}
else if (ce->type && (t = ce->type->toBasetype()) != NULL &&
(t->ty == Tstruct || t->ty == Tclass))
@@ -1473,6 +1469,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
if (t && t->ty == Tfunction)
e = new CallExp(e->loc, e);
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e));
v->storage_class |= STCtemp;
}
else
{ /* For arrays, $ will either be a compile-time constant
@@ -1483,7 +1480,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
VoidInitializer *e = new VoidInitializer(Loc());
e->type = Type::tsize_t;
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e);
v->storage_class |= STCctfe; // it's never a true static variable
v->storage_class |= STCtemp | STCctfe; // it's never a true static variable
}
*pvar = v;
}
+3 -7
View File
@@ -146,7 +146,7 @@ public:
Symbol *csym; // symbol for code generator
Symbol *isym; // import version of csym
#endif
utf8_t *comment; // documentation comment for this Dsymbol
const utf8_t *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
bool errors; // this symbol failed to pass semantic()
@@ -211,10 +211,8 @@ public:
virtual bool isExport(); // is Dsymbol exported?
virtual bool isImportedSymbol(); // is Dsymbol imported?
virtual bool isDeprecated(); // is Dsymbol deprecated?
#if DMDV2
virtual bool isOverloadable();
virtual bool hasOverloads();
#endif
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type?
@@ -230,7 +228,7 @@ public:
virtual void addLocalClass(ClassDeclarations *) { }
virtual void checkCtorConstInit() { }
virtual void addComment(utf8_t *comment);
virtual void addComment(const utf8_t *comment);
virtual void emitComment(Scope *sc);
void emitDitto(Scope *sc);
@@ -310,7 +308,7 @@ public:
DsymbolTable *symtab; // members[] sorted into table
Dsymbols *imports; // imported Dsymbol's
unsigned char *prots; // array of PROT, one for each import
PROT *prots; // array of PROT, one for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
@@ -370,7 +368,6 @@ public:
// Overload Sets
#if DMDV2
class OverloadSet : public Dsymbol
{
public:
@@ -381,7 +378,6 @@ public:
OverloadSet *isOverloadSet() { return this; }
const char *kind();
};
#endif
// Table of Dsymbol's
+1 -1
View File
@@ -2374,7 +2374,7 @@ static NameId* namesTable[] = {
namesS, namesT, namesU, namesV, namesW, namesX, namesY, namesZ, NULL
};
int HtmlNamedEntity(utf8_t *p, size_t length)
int HtmlNamedEntity(const utf8_t *p, size_t length)
{
int tableIndex = tolower(*p) - 'a';
if (tableIndex >= 0 && tableIndex < 26)
+4 -3
View File
@@ -381,20 +381,21 @@ Type *EnumDeclaration::getMemtype(Loc loc)
if (loc.linnum == 0)
loc = this->loc;
if (scope)
{ /* Enum is forward referenced. We don't need to resolve the whole thing,
{
/* Enum is forward referenced. We don't need to resolve the whole thing,
* just the base type
*/
if (memtype)
memtype = memtype->semantic(loc, scope);
else
{
if (!isAnonymous())
if (!isAnonymous() && members)
memtype = Type::tint32;
}
}
if (!memtype)
{
if (!isAnonymous())
if (!isAnonymous() && members)
memtype = Type::tint32;
else
{
-2
View File
@@ -57,9 +57,7 @@ public:
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *getType();
const char *kind();
#if DMDV2
Dsymbol *search(Loc, Identifier *ident, int flags);
#endif
bool isDeprecated(); // is Dsymbol deprecated?
PROT prot();
Expression *getMaxMinValue(Loc loc, Identifier *id);
+536 -603
View File
File diff suppressed because it is too large Load Diff
+114 -59
View File
@@ -104,14 +104,14 @@ int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s);
Expression *valueNoDtor(Expression *e);
int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
#if DMDV2
Expression *resolveAliasThis(Scope *sc, Expression *e);
Expression *callCpCtor(Scope *sc, Expression *e);
#endif
Expression *resolveOpDollar(Scope *sc, ArrayExp *ae);
Expression *resolveOpDollar(Scope *sc, SliceExp *se);
Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc);
AggregateDeclaration *isAggregate(Type *t);
/* Run CTFE on the expression, but allow the expression to be a TypeExp
* or a tuple containing a TypeExp. (This is required by pragma(msg)).
*/
@@ -197,7 +197,6 @@ public:
Expression *addressOf(Scope *sc);
Expression *deref();
Expression *integralPromotions(Scope *sc);
Expression *isTemp();
Expression *toDelegate(Scope *sc, Type *t);
@@ -216,7 +215,7 @@ public:
bool hasSideEffect();
void discardValue();
void useValue();
int canThrow(bool mustNotThrow);
bool canThrow(bool mustNotThrow);
virtual int inlineCost3(InlineCostState *ics);
virtual Expression *doInline(InlineDoState *ids);
@@ -467,7 +466,7 @@ public:
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
unsigned charAt(size_t i);
unsigned charAt(uinteger_t i);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
elem *toElem(IRState *irs);
@@ -626,6 +625,7 @@ public:
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *addDtorHook(Scope *sc);
#if IN_LLVM
// With the introduction of pointers returned from CTFE, struct literals can
// now contain pointers to themselves. While in toElem, contains a pointer
@@ -742,7 +742,6 @@ public:
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#if DMDV2
class SymbolExp : public Expression
{
public:
@@ -753,16 +752,15 @@ public:
elem *toElem(IRState *irs);
};
#endif
// Offset from symbol
class SymOffExp : public SymbolExp
{
public:
unsigned offset;
dinteger_t offset;
SymOffExp(Loc loc, Declaration *var, unsigned offset, bool hasOverloads = false);
SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads = false);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
@@ -814,7 +812,6 @@ public:
//Expression *inlineScan(InlineScanState *iss);
};
#if DMDV2
// Overload Set
class OverExp : public Expression
@@ -827,7 +824,6 @@ public:
Expression *toLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
// Function/Delegate literal
@@ -892,7 +888,6 @@ public:
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#if DMDV2
class TraitsExp : public Expression
{
public:
@@ -902,9 +897,11 @@ public:
TraitsExp(Loc loc, Identifier *ident, Objects *args);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *isTypeX(bool (*fp)(Type *t));
Expression *isFuncX(bool (*fp)(FuncDeclaration *f));
Expression *isDeclX(bool (*fp)(Declaration *d));
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
class HaltExp : public Expression
{
@@ -1177,11 +1174,13 @@ public:
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *addDtorHook(Scope *sc);
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
Expression *inlineScan(InlineScanState *iss, Expression *eret);
#if IN_LLVM
void cacheLvalue(IRState* p);
@@ -1307,10 +1306,10 @@ class CastExp : public UnaExp
public:
// Possible to cast to one type while painting to another type
Type *to; // type to cast to
unsigned mod; // MODxxxxx
unsigned char mod; // MODxxxxx
CastExp(Loc loc, Expression *e, Type *t);
CastExp(Loc loc, Expression *e, unsigned mod);
CastExp(Loc loc, Expression *e, unsigned char mod);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
MATCH implicitConvTo(Type *t);
@@ -1517,6 +1516,9 @@ public:
Identifier *opId(); // For operator overloading
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
Expression *inlineScan(InlineScanState *iss);
elem *toElem(IRState *irs);
#if IN_LLVM
@@ -1530,53 +1532,111 @@ public:
ConstructExp(Loc loc, Expression *e1, Expression *e2);
};
#define ASSIGNEXP(op) \
class op##AssignExp : public BinAssignExp \
{ \
public: \
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
S(Expression *semantic(Scope *sc);) \
\
Identifier *opId(); /* For operator overloading */ \
\
elem *toElem(IRState *irs); \
class AddAssignExp : public BinAssignExp
{
public:
AddAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
#define X(a) a
#define S(a)
ASSIGNEXP(Add)
ASSIGNEXP(Min)
ASSIGNEXP(Mul)
ASSIGNEXP(Div)
ASSIGNEXP(Mod)
ASSIGNEXP(And)
ASSIGNEXP(Or)
ASSIGNEXP(Xor)
#undef S
class MinAssignExp : public BinAssignExp
{
public:
MinAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
#if DMDV2
#define S(a) a
ASSIGNEXP(Pow)
#undef S
#endif
class MulAssignExp : public BinAssignExp
{
public:
MulAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
#undef S
#undef X
class DivAssignExp : public BinAssignExp
{
public:
DivAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
#define X(a)
class ModAssignExp : public BinAssignExp
{
public:
ModAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
#define S(a)
ASSIGNEXP(Shl)
ASSIGNEXP(Shr)
ASSIGNEXP(Ushr)
#undef S
class AndAssignExp : public BinAssignExp
{
public:
AndAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
#define S(a) a
ASSIGNEXP(Cat)
#undef S
class OrAssignExp : public BinAssignExp
{
public:
OrAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
#undef X
#undef ASSIGNEXP
class XorAssignExp : public BinAssignExp
{
public:
XorAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
class PowAssignExp : public BinAssignExp
{
public:
PowAssignExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
class ShlAssignExp : public BinAssignExp
{
public:
ShlAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
class ShrAssignExp : public BinAssignExp
{
public:
ShrAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
class UshrAssignExp : public BinAssignExp
{
public:
UshrAssignExp(Loc loc, Expression *e1, Expression *e2);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
class CatAssignExp : public BinAssignExp
{
public:
CatAssignExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Identifier *opId(); /* For operator overloading */
elem *toElem(IRState *irs);
};
class AddExp : public BinExp
{
@@ -1678,7 +1738,6 @@ public:
elem *toElem(IRState *irs);
};
#if DMDV2
class PowExp : public BinExp
{
public:
@@ -1692,7 +1751,6 @@ public:
elem *toElem(IRState *irs);
};
#endif
class ShlExp : public BinExp
{
@@ -1914,7 +1972,6 @@ public:
elem *toElem(IRState *irs);
};
#if DMDV2
/****************************************************************/
class DefaultInitExp : public Expression
@@ -1966,8 +2023,6 @@ public:
Expression *resolveLoc(Loc loc, Scope *sc);
};
#endif
/****************************************************************/
#if IN_LLVM
+168 -127
View File
@@ -79,9 +79,6 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
isArrayOp = 0;
dArrayOp = NULL;
semantic3Errors = 0;
#if DMDV1
nestedFrameRef = 0;
#endif
fes = NULL;
introducing = 0;
tintro = NULL;
@@ -96,13 +93,12 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
#if IN_DMD
shidden = NULL;
#endif
#if DMDV2
builtin = BUILTINunknown;
tookAddressOf = 0;
requiresClosure = false;
flags = 0;
#endif
returns = NULL;
gotos = NULL;
#if IN_LLVM
// LDC
@@ -165,7 +161,6 @@ static Parameters *outToRef(Parameters* params)
void FuncDeclaration::semantic(Scope *sc)
{ TypeFunction *f;
AggregateDeclaration *ad;
StructDeclaration *sd;
ClassDeclaration *cd;
InterfaceDeclaration *id;
bool doesoverride;
@@ -215,6 +210,8 @@ void FuncDeclaration::semantic(Scope *sc)
if (StructDeclaration *sd = ad->isStructDeclaration())
sd->makeNested();
}
if (sc->func)
storage_class |= sc->func->storage_class & STCdisable;
// Remove prefix storage classes silently.
if ((storage_class & STC_TYPECTOR) && !(ad || isNested()))
storage_class &= ~STC_TYPECTOR;
@@ -223,7 +220,17 @@ void FuncDeclaration::semantic(Scope *sc)
FuncLiteralDeclaration *fld = isFuncLiteralDeclaration();
if (fld && fld->treq)
linkage = ((TypeFunction *)fld->treq->nextOf())->linkage;
{
Type *treq = fld->treq;
assert(treq->nextOf()->ty == Tfunction);
if (treq->ty == Tdelegate)
fld->tok = TOKdelegate;
else if (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction)
fld->tok = TOKfunction;
else
assert(0);
linkage = ((TypeFunction *)treq->nextOf())->linkage;
}
else
linkage = sc->linkage;
protection = sc->protection;
@@ -360,7 +367,12 @@ void FuncDeclaration::semantic(Scope *sc)
storage_class &= ~STCref;
if (type->ty != Tfunction)
{
error("%s must be a function instead of %s", toChars(), type->toChars());
if (type->ty != Terror)
{
error("%s must be a function instead of %s", toChars(), type->toChars());
type = Type::terror;
}
errors = true;
return;
}
f = (TypeFunction *)type;
@@ -407,7 +419,7 @@ void FuncDeclaration::semantic(Scope *sc)
}
#endif
sd = parent->isStructDeclaration();
StructDeclaration *sd = parent->isStructDeclaration();
if (sd)
{
if (isCtorDeclaration())
@@ -446,9 +458,7 @@ void FuncDeclaration::semantic(Scope *sc)
storage_class |= STCabstract;
if (isCtorDeclaration() ||
#if DMDV2
isPostBlitDeclaration() ||
#endif
isDtorDeclaration() ||
isInvariantDeclaration() ||
isNewDeclaration() || isDelete())
@@ -496,12 +506,12 @@ void FuncDeclaration::semantic(Scope *sc)
continue;
for (size_t j = 0; j < cbd->vtbl.dim; j++)
{
FuncDeclaration *f = cbd->vtbl[j]->isFuncDeclaration();
if (!f || f->ident != ident)
FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration();
if (!f2 || f2->ident != ident)
continue;
if (cbd->parent && cbd->parent->isTemplateInstance())
{
if (!f->functionSemantic())
if (!f2->functionSemantic())
goto Ldone;
}
may_override = true;
@@ -521,7 +531,7 @@ void FuncDeclaration::semantic(Scope *sc)
vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
: -1;
doesoverride = FALSE;
doesoverride = false;
switch (vi)
{
case (size_t)-1:
@@ -536,12 +546,12 @@ void FuncDeclaration::semantic(Scope *sc)
{ Dsymbol *s = cd->baseClass->search(loc, ident, 0);
if (s)
{
FuncDeclaration *f = s->isFuncDeclaration();
if (f)
FuncDeclaration *f2 = s->isFuncDeclaration();
if (f2)
{
f = f->overloadExactMatch(type);
if (f && f->isFinalFunc() && f->prot() != PROTprivate)
error("cannot override final function %s", f->toPrettyChars());
f2 = f2->overloadExactMatch(type);
if (f2 && f2->isFinalFunc() && f2->prot() != PROTprivate)
error("cannot override final function %s", f2->toPrettyChars());
}
}
}
@@ -576,7 +586,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (fdc == this)
{
doesoverride = TRUE;
doesoverride = true;
break;
}
@@ -596,11 +606,9 @@ void FuncDeclaration::semantic(Scope *sc)
if (fdv->isFinalFunc())
error("cannot override final function %s", fdv->toPrettyChars());
doesoverride = TRUE;
#if DMDV2
doesoverride = true;
if (!isOverride())
::deprecation(loc, "overriding base class function without using override attribute is deprecated (%s overrides %s)", toPrettyChars(), fdv->toPrettyChars());
#endif
if (fdc->toParent() == parent)
{
@@ -675,13 +683,11 @@ void FuncDeclaration::semantic(Scope *sc)
*/
foverrides.push(fdv);
#if DMDV2
/* Should we really require 'override' when implementing
* an interface function?
*/
//if (!isOverride())
//warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
#endif
if (fdv->tintro)
ti = fdv->tintro;
@@ -754,12 +760,12 @@ void FuncDeclaration::semantic(Scope *sc)
Dsymbol *s = search_function(b->base, ident);
if (s)
{
FuncDeclaration *f = s->isFuncDeclaration();
if (f)
FuncDeclaration *f2 = s->isFuncDeclaration();
if (f2)
{
f = f->overloadExactMatch(type);
if (f && f->isFinalFunc() && f->prot() != PROTprivate)
error("cannot override final function %s.%s", b->base->toChars(), f->toPrettyChars());
f2 = f2->overloadExactMatch(type);
if (f2 && f2->isFinalFunc() && f2->prot() != PROTprivate)
error("cannot override final function %s.%s", b->base->toChars(), f2->toPrettyChars());
}
}
}
@@ -790,10 +796,10 @@ void FuncDeclaration::semantic(Scope *sc)
}
// If it's a member template
ClassDeclaration *cd = ti->tempdecl->isClassMember();
if (cd)
ClassDeclaration *cd2 = ti->tempdecl->isClassMember();
if (cd2)
{
error("cannot use template to add virtual function to class '%s'", cd->toChars());
error("cannot use template to add virtual function to class '%s'", cd2->toChars());
}
}
}
@@ -985,14 +991,14 @@ Ldone:
{
printedMain = true;
const char *name = FileName::searchPath(global.path, mod->srcfile->toChars(), 1);
printf("entry %-10s\t%s\n", type, name);
fprintf(global.stdmsg, "entry %-10s\t%s\n", type, name);
}
}
if (fbody && isMain() && sc->module->isRoot())
genCmain(sc);
return;
assert(type->ty != Terror || errors);
}
void FuncDeclaration::semantic2(Scope *sc)
@@ -1133,8 +1139,6 @@ void FuncDeclaration::semantic3(Scope *sc)
// Declare hidden variable _arguments[] and _argptr
if (f->varargs == 1)
{
Type *t;
#if !IN_GCC && !IN_LLVM
if (global.params.is64bit && !global.params.isWindows)
{ // Declare save area for varargs registers
@@ -1148,6 +1152,7 @@ void FuncDeclaration::semantic3(Scope *sc)
else
{
v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
v_argsave->storage_class |= STCtemp;
v_argsave->semantic(sc2);
sc2->insert(v_argsave);
v_argsave->parent = this;
@@ -1158,22 +1163,24 @@ void FuncDeclaration::semantic3(Scope *sc)
if (f->linkage == LINKd)
{ // Declare _arguments[]
v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
v_arguments->storage_class = STCparameter;
v_arguments->storage_class |= STCtemp | STCparameter;
v_arguments->semantic(sc2);
sc2->insert(v_arguments);
v_arguments->parent = this;
//t = Type::typeinfo->type->constOf()->arrayOf();
t = Type::dtypeinfo->type->arrayOf();
//Type *t = Type::typeinfo->type->constOf()->arrayOf();
Type *t = Type::dtypeinfo->type->arrayOf();
_arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
_arguments->storage_class |= STCtemp;
_arguments->semantic(sc2);
sc2->insert(_arguments);
_arguments->parent = this;
}
if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
{ // Declare _argptr
t = Type::tvalist;
Type *t = Type::tvalist;
argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
argptr->storage_class |= STCtemp;
argptr->semantic(sc2);
sc2->insert(argptr);
argptr->parent = this;
@@ -1237,20 +1244,23 @@ void FuncDeclaration::semantic3(Scope *sc)
{
Parameter *arg = Parameter::getNth(f->parameters, i);
Identifier *id = arg->ident;
StorageClass stc = 0;
if (!id)
{
/* Generate identifier for un-named parameter,
* because we need it later on.
*/
arg->ident = id = Identifier::generateId("_param_", i);
stc |= STCtemp;
}
Type *vtype = arg->type;
VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
v->storage_class |= STCparameter;
stc |= STCparameter;
if (f->varargs == 2 && i + 1 == nparams)
v->storage_class |= STCvariadic;
v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
stc |= STCvariadic;
stc |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
v->storage_class = stc;
v->semantic(sc2);
if (!sc2->insert(v))
error("parameter %s.%s is already defined", toChars(), v->toChars());
@@ -1410,17 +1420,17 @@ void FuncDeclaration::semantic3(Scope *sc)
sym->parent = sc2->scopesym;
sc2 = sc2->push(sym);
AggregateDeclaration *ad = isAggregateMember2();
AggregateDeclaration *ad2 = isAggregateMember2();
/* If this is a class constructor
*/
if (ad && isCtorDeclaration())
if (ad2 && isCtorDeclaration())
{
sc2->fieldinit = new unsigned[ad->fields.dim];
sc2->fieldinit_dim = ad->fields.dim;
for (size_t i = 0; i < ad->fields.dim; i++)
sc2->fieldinit = (unsigned *)mem.malloc(sizeof(unsigned) * ad2->fields.dim);
sc2->fieldinit_dim = ad2->fields.dim;
for (size_t i = 0; i < ad2->fields.dim; i++)
{
VarDeclaration *v = ad->fields[i];
VarDeclaration *v = ad2->fields[i];
v->ctorinit = 0;
sc2->fieldinit[i] = 0;
}
@@ -1483,26 +1493,15 @@ void FuncDeclaration::semantic3(Scope *sc)
if (fbody->isErrorStatement())
;
else if (isCtorDeclaration() && ad)
else if (isCtorDeclaration() && ad2)
{
#if DMDV2
// Check for errors related to 'nothrow'.
int nothrowErrors = global.errors;
int blockexit = fbody->blockExit(f->isnothrow);
if (f->isnothrow && (global.errors != nothrowErrors) )
::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars());
if (flags & FUNCFLAGnothrowInprocess)
f->isnothrow = !(blockexit & BEthrow);
#endif
//printf("callSuper = x%x\n", sc2->callSuper);
ClassDeclaration *cd = ad->isClassDeclaration();
ClassDeclaration *cd = ad2->isClassDeclaration();
// Verify that all the ctorinit fields got initialized
if (!(sc2->callSuper & CSXthis_ctor))
{
for (size_t i = 0; i < ad->fields.dim; i++)
{ VarDeclaration *v = ad->fields[i];
for (size_t i = 0; i < ad2->fields.dim; i++)
{ VarDeclaration *v = ad2->fields[i];
if (v->ctorinit == 0)
{
@@ -1530,7 +1529,7 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
}
delete[] sc2->fieldinit;
mem.free(sc2->fieldinit);
sc2->fieldinit = NULL;
sc2->fieldinit_dim = 0;
@@ -1556,6 +1555,15 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
// Check for errors related to 'nothrow'.
int nothrowErrors = global.errors;
int blockexit = fbody->blockExit(f->isnothrow);
if (f->isnothrow && (global.errors != nothrowErrors) )
::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars());
if (flags & FUNCFLAGnothrowInprocess)
f->isnothrow = !(blockexit & BEthrow);
//printf("callSuper = x%x\n", sc2->callSuper);
/* Append:
* return this;
* to function body
@@ -1585,7 +1593,6 @@ void FuncDeclaration::semantic3(Scope *sc)
}
else
{
#if DMDV2
// Check for errors related to 'nothrow'.
int nothrowErrors = global.errors;
int blockexit = fbody->blockExit(f->isnothrow);
@@ -1598,16 +1605,11 @@ void FuncDeclaration::semantic3(Scope *sc)
}
int offend = blockexit & BEfallthru;
#endif
if (type->nextOf()->ty != Tvoid)
{
if (offend)
{ Expression *e;
#if DMDV1
warning(loc, "no return exp; or assert(0); at end of function");
#else
error("no return exp; or assert(0); at end of function");
#endif
if (global.params.useAssert &&
!global.params.useInline)
{ /* Add an assert(0, msg); where the missing return
@@ -1785,7 +1787,7 @@ void FuncDeclaration::semantic3(Scope *sc)
e = new AssignExp(Loc(), e1, e);
e->type = t;
a->push(new ExpStatement(Loc(), e));
p->isargptr = TRUE;
p->isargptr = true;
}
#endif
}
@@ -1866,7 +1868,6 @@ void FuncDeclaration::semantic3(Scope *sc)
}
fbody = new CompoundStatement(Loc(), a);
#if DMDV2
/* Append destructor calls for parameters as finally blocks.
*/
if (parameters)
@@ -1890,7 +1891,7 @@ void FuncDeclaration::semantic3(Scope *sc)
if (f->isnothrow && (global.errors != nothrowErrors) )
::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars());
if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
f->isnothrow = FALSE;
f->isnothrow = false;
if (fbody->blockExit(f->isnothrow) == BEfallthru)
fbody = new CompoundStatement(Loc(), fbody, s);
else
@@ -1900,13 +1901,11 @@ void FuncDeclaration::semantic3(Scope *sc)
}
// from this point on all possible 'throwers' are checked
flags &= ~FUNCFLAGnothrowInprocess;
#endif
if (isSynchronized())
{ /* Wrap the entire function body in a synchronized statement
*/
AggregateDeclaration *ad = isThis();
ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration();
ClassDeclaration *cd = isThis() ? isThis()->isClassDeclaration() : parent->isClassDeclaration();
if (cd)
{
@@ -1941,6 +1940,15 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
// Fix up forward-referenced gotos
if (gotos)
{
for (size_t i = 0; i < gotos->dim; ++i)
{
(*gotos)[i]->checkLabel();
}
}
sc2->callSuper = 0;
sc2->pop();
}
@@ -1991,6 +1999,8 @@ void FuncDeclaration::semantic3(Scope *sc)
semanticRun = PASSsemantic3done;
semantic3Errors = global.errors - nerrors;
}
if (type->ty == Terror)
errors = true;
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
//fflush(stdout);
}
@@ -2010,7 +2020,7 @@ bool FuncDeclaration::functionSemantic()
semantic(scope);
global.gag = oldgag;
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
spec->errors = global.errors - olderrs != 0;
if (olderrs != global.errors) // if errors compiling this function
return false;
}
@@ -2060,7 +2070,7 @@ bool FuncDeclaration::functionSemantic3()
// If it is a speculatively-instantiated template, and errors occur,
// we need to mark the template as having errors.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
spec->errors = global.errors - olderrs != 0;
if (olderrs != global.errors) // if errors compiling this function
return false;
}
@@ -2074,9 +2084,9 @@ void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
StorageClassDeclaration::stcToCBuffer(buf, storage_class);
type->toCBuffer(buf, ident, hgs);
if(hgs->hdrgen == 1)
if (hgs->hdrgen == 1)
{
if(storage_class & STCauto)
if (storage_class & STCauto)
{
hgs->autoMember++;
bodyToCBuffer(buf, hgs);
@@ -2202,7 +2212,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("out");
if (outId)
{ buf->writebyte('(');
{
buf->writebyte('(');
buf->writestring(outId->toChars());
buf->writebyte(')');
}
@@ -2228,7 +2239,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
hgs->autoMember = saveauto;
}
else
{ buf->writeByte(';');
{
buf->writeByte(';');
buf->writenl();
}
}
@@ -2255,16 +2267,15 @@ void FuncDeclaration::buildResultVar()
outId = Id::result; // provide a default
VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
if (outId == Id::result) v->storage_class |= STCtemp;
v->noscope = 1;
v->storage_class |= STCresult;
#if DMDV2
if (!isVirtual())
v->storage_class |= STCconst;
if (tf->isref)
{
v->storage_class |= STCref | STCforeach;
}
#endif
v->semantic(scout);
if (!scout->insert(v))
error("out result %s is already defined", v->toChars());
@@ -2445,6 +2456,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Identifier *oid)
*/
ExpInitializer *ei = new ExpInitializer(Loc(), eresult);
VarDeclaration *v = new VarDeclaration(Loc(), t1, Lexer::uniqueId("__covres"), ei);
v->storage_class |= STCtemp;
DeclarationExp *de = new DeclarationExp(Loc(), v);
VarExp *ve = new VarExp(Loc(), v);
eresult = new CommaExp(Loc(), de, ve);
@@ -2578,6 +2590,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
bool FuncDeclaration::overloadInsert(Dsymbol *s)
{
//printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
assert(s != this);
AliasDeclaration *ad = s->isAliasDeclaration();
if (ad)
{
@@ -2598,7 +2612,7 @@ bool FuncDeclaration::overloadInsert(Dsymbol *s)
if (overnext)
return overnext->overloadInsert(td);
overnext = td;
return TRUE;
return true;
}
FuncDeclaration *fd = s->isFuncDeclaration();
if (!fd)
@@ -2620,7 +2634,7 @@ bool FuncDeclaration::overloadInsert(Dsymbol *s)
!isFuncAliasDeclaration())
{
//printf("\tfalse: conflict %s\n", kind());
return FALSE;
return false;
}
#endif
@@ -2760,7 +2774,6 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
return 1;
}
#if DMDV2
/* Allow covariant matches, as long as the return type
* is just a const conversion.
* This allows things like pure functions to match with an impure function type.
@@ -2774,7 +2787,6 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
return 1;
}
}
#endif
return 0;
}
};
@@ -2788,7 +2800,7 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
static void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod)
{
bool bothMutable = ((lhsMod & rhsMod) == 0);
bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared);
bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared) != 0;
bool sharedMismatchOnly = ((lhsMod ^ rhsMod) == MODshared);
if (lhsMod & MODshared)
@@ -3006,7 +3018,6 @@ Lerror:
if (tthis)
tthis->modToBuffer(&fargsBuf);
assert(!m.lastf || m.nextf);
if (!m.lastf && !(flags & 1)) // no match
{
if (td)
@@ -3202,12 +3213,17 @@ int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
return level;
Lerr:
Dsymbol *p = toParent2();
while (p->toParent2()->isFuncDeclaration())
p = p->toParent2();
// Don't give error if in template constraint
if (!((sc->flags & SCOPEstaticif) && parent->isTemplateDeclaration()))
if (!(sc->flags & SCOPEstaticif) && !p->parent->isTemplateDeclaration())
{
const char *xstatic = isStatic() ? "static " : "";
// better diagnostics for static functions
::error(loc, "%s%s %s cannot access frame of function %s",
isStatic() ? "static " : "", kind(), toPrettyChars(), fd->toPrettyChars());
xstatic, kind(), toPrettyChars(), fd->toPrettyChars());
}
return 1;
}
@@ -3414,7 +3430,7 @@ PURE FuncDeclaration::isPureBypassingInference()
/**************************************
* The function is doing something impure,
* so mark it as impure.
* If there's a purity error, return TRUE.
* If there's a purity error, return true.
*/
bool FuncDeclaration::setImpure()
{
@@ -3423,8 +3439,8 @@ bool FuncDeclaration::setImpure()
flags &= ~FUNCFLAGpurityInprocess;
}
else if (isPure())
return TRUE;
return FALSE;
return true;
return false;
}
bool FuncDeclaration::isSafe()
@@ -3454,7 +3470,7 @@ bool FuncDeclaration::isTrusted()
/**************************************
* The function is doing something unsave,
* so mark it as unsafe.
* If there's a safe error, return TRUE.
* If there's a safe error, return true.
*/
bool FuncDeclaration::setUnsafe()
{
@@ -3464,8 +3480,8 @@ bool FuncDeclaration::setUnsafe()
((TypeFunction *)type)->trust = TRUSTsystem;
}
else if (isSafe())
return TRUE;
return FALSE;
return true;
return false;
}
/**************************************
@@ -3737,7 +3753,7 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
//printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
//printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars());
//printf("fdv2 = %s in [%s]\n", fdv2->toChars(), fdv2->loc.toChars());
//printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
if (fdv2 && fdthis && fdv2 != fdthis)
@@ -3747,19 +3763,20 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
bool found = false;
for (int i = 0; i < siblingCallers.dim; ++i)
{ if (siblingCallers[i] == fdthis)
{
if (siblingCallers[i] == fdthis)
found = true;
}
if (!found)
{
//printf("\tadding sibling %s\n", fdthis->toPrettyChars());
siblingCallers.push(fdthis);
if (!sc->intypeof && !(sc->flags & SCOPEcompile))
siblingCallers.push(fdthis);
}
}
}
FuncDeclaration *fdv = toParent()->isFuncDeclaration();
fdv = toParent()->isFuncDeclaration();
FuncDeclaration *fdv = toParent2()->isFuncDeclaration();
if (fdv && fdthis && fdv != fdthis)
{
int lv = fdthis->getLevel(loc, sc, fdv);
@@ -3806,8 +3823,18 @@ void markAsNeedingClosure(Dsymbol *f, FuncDeclaration *outerFunc)
* Note that nested functions can only call lexically earlier nested
* functions, so loops are impossible.
*/
bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc, void *p = NULL)
{
struct PrevSibling
{
PrevSibling *p;
FuncDeclaration *f;
};
PrevSibling ps;
ps.p = (PrevSibling *)p;
ps.f = f;
//printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars());
bool bAnyClosures = false;
for (int i = 0; i < f->siblingCallers.dim; ++i)
@@ -3818,7 +3845,19 @@ bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
markAsNeedingClosure(g, outerFunc);
bAnyClosures = true;
}
bAnyClosures |= checkEscapingSiblings(g, outerFunc);
PrevSibling *prev = (PrevSibling *)p;
while (1)
{
if (!prev)
{
bAnyClosures |= checkEscapingSiblings(g, outerFunc, &ps);
break;
}
if (prev->f == g)
break;
prev = prev->p;
}
}
//printf("\t%d\n", bAnyClosures);
return bAnyClosures;
@@ -3831,7 +3870,6 @@ bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
* created for them.
*/
#if DMDV2
bool FuncDeclaration::needsClosure()
{
/* Need a closure for all the closureVars[] if any of the
@@ -3926,7 +3964,6 @@ Lyes:
//printf("\tneeds closure\n");
return true;
}
#endif
/***********************************************
* Determine if function's variables are referenced by a function
@@ -3935,11 +3972,7 @@ Lyes:
bool FuncDeclaration::hasNestedFrameRefs()
{
#if DMDV2
if (closureVars.dim)
#else
if (nestedFrameRef)
#endif
return true;
/* If a virtual method has contracts, assume its variables are referenced
@@ -4108,6 +4141,16 @@ void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
}
}
const char *FuncLiteralDeclaration::toPrettyChars()
{
if (parent)
{
TemplateInstance *ti = parent->isTemplateInstance();
if (ti)
return ti->tempdecl->toPrettyChars();
}
return Dsymbol::toPrettyChars();
}
/********************************* CtorDeclaration ****************************/
@@ -4167,7 +4210,7 @@ void CtorDeclaration::semantic(Scope *sc)
storage_class |= STCdisable;
fbody = NULL;
}
sd->noDefaultCtor = TRUE;
sd->noDefaultCtor = true;
}
else
{
@@ -4204,7 +4247,6 @@ bool CtorDeclaration::addPostInvariant()
/********************************* PostBlitDeclaration ****************************/
#if DMDV2
PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
: FuncDeclaration(loc, endloc, id, stc, NULL)
{
@@ -4238,7 +4280,7 @@ void PostBlitDeclaration::semantic(Scope *sc)
ad->postblits.push(this);
if (!type)
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class);
type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
sc = sc->push();
sc->stc &= ~STCstatic; // not static
@@ -4274,7 +4316,6 @@ void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("this(this)");
bodyToCBuffer(buf, hgs);
}
#endif
/********************************* DtorDeclaration ****************************/
@@ -4318,7 +4359,7 @@ void DtorDeclaration::semantic(Scope *sc)
ad->dtors.push(this);
if (!type)
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class);
type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
sc = sc->push();
sc->stc &= ~STCstatic; // not a static destructor
@@ -4398,7 +4439,7 @@ void StaticCtorDeclaration::semantic(Scope *sc)
}
if (!type)
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
type = new TypeFunction(NULL, Type::tvoid, false, LINKd);
/* If the static ctor appears within a template instantiation,
* it could get called multiple times by the module constructors
@@ -4414,7 +4455,7 @@ void StaticCtorDeclaration::semantic(Scope *sc)
*/
Identifier *id = Lexer::idPool("__gate");
VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL);
v->storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls;
v->storage_class = STCtemp | (isSharedStaticCtorDeclaration() ? STCstatic : STCtls);
Statements *sa = new Statements();
Statement *s = new ExpStatement(Loc(), v);
sa->push(s);
@@ -4452,7 +4493,7 @@ bool StaticCtorDeclaration::isVirtual()
bool StaticCtorDeclaration::hasStaticCtorOrDtor()
{
return TRUE;
return true;
}
bool StaticCtorDeclaration::addPreInvariant()
@@ -4529,7 +4570,7 @@ void StaticDtorDeclaration::semantic(Scope *sc)
}
if (!type)
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class);
type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
/* If the static ctor appears within a template instantiation,
* it could get called multiple times by the module constructors
@@ -4546,7 +4587,7 @@ void StaticDtorDeclaration::semantic(Scope *sc)
*/
Identifier *id = Lexer::idPool("__gate");
VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL);
v->storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls;
v->storage_class = STCtemp | (isSharedStaticDtorDeclaration() ? STCstatic : STCtls);
Statements *sa = new Statements();
Statement *s = new ExpStatement(Loc(), v);
sa->push(s);
@@ -4585,7 +4626,7 @@ bool StaticDtorDeclaration::isVirtual()
bool StaticDtorDeclaration::hasStaticCtorOrDtor()
{
return TRUE;
return true;
}
bool StaticDtorDeclaration::addPreInvariant()
@@ -4669,7 +4710,7 @@ void InvariantDeclaration::semantic(Scope *sc)
ad->invs.push(this);
}
if (!type)
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class);
type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
sc = sc->push();
sc->stc &= ~STCstatic; // not a static invariant
@@ -4752,7 +4793,7 @@ void UnitTestDeclaration::semantic(Scope *sc)
if (global.params.useUnitTests)
{
if (!type)
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
type = new TypeFunction(NULL, Type::tvoid, false, LINKd);
Scope *sc2 = sc->push();
sc2->linkage = LINKd;
FuncDeclaration::semantic(sc2);
-3
View File
@@ -18,9 +18,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#if __DMC__
#include <complex.h>
#endif
#include "rmem.h"
-5
View File
@@ -25,11 +25,6 @@ Identifier::Identifier(const char *string, int value)
this->len = strlen(string);
}
hash_t Identifier::hashCode()
{
return String::calcHash(string);
}
bool Identifier::equals(RootObject *o)
{
#if IN_LLVM // ASan
-1
View File
@@ -26,7 +26,6 @@ public:
Identifier(const char *string, int value);
bool equals(RootObject *o);
hash_t hashCode();
int compare(RootObject *o);
void print();
char *toChars();
+1 -4
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -405,9 +405,6 @@ int main()
}
fprintf(fp, "// File generated by idgen.c\n");
#if __DMC__
fprintf(fp, "#pragma once\n");
#endif
fprintf(fp, "#ifndef DMD_ID_H\n");
fprintf(fp, "#define DMD_ID_H 1\n");
fprintf(fp, "class Identifier;\n");
-16
View File
@@ -27,21 +27,6 @@
const char *importHint(const char *s)
{
#if DMDV1
static const char *modules[] =
{ "std.c.stdio",
"std.stdio",
"std.math",
"std.c.stdarg",
};
static const char *names[] =
{
"printf", NULL,
"writefln", NULL,
"sin", "cos", "sqrt", "fabs", NULL,
"__va_argsave_t", NULL,
};
#else
static const char *modules[] =
{ "core.stdc.stdio",
"std.stdio",
@@ -55,7 +40,6 @@ const char *importHint(const char *s)
"sin", "cos", "sqrt", "fabs", NULL,
"__va_argsave_t", NULL,
};
#endif
int m = 0;
for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++)
{
+1 -1
View File
@@ -289,7 +289,7 @@ void Import::semantic(Scope *sc)
* ModuleAliasIdentifier ] "\n"
*
* BasicImportDeclaration
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
*
* FilePath
+25 -15
View File
@@ -287,13 +287,14 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
ExpInitializer *ie = new ExpInitializer(loc, e);
return ie->semantic(sc, t, needInterpret);
}
else if (t->ty == Tdelegate && value.dim == 0)
else if ((t->ty == Tdelegate || t->ty == Tpointer && t->nextOf()->ty == Tfunction) && value.dim == 0)
{
TOK tok = (t->ty == Tdelegate) ? TOKdelegate : TOKfunction;
/* Rewrite as empty delegate literal { }
*/
Parameters *arguments = new Parameters;
Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, TOKdelegate, NULL);
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, tok, NULL);
fd->fbody = new CompoundStatement(loc, new Statements());
fd->endloc = loc;
Expression *e = new FuncExp(loc, fd);
@@ -387,12 +388,9 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
if (sem) // if semantic() already run
return this;
sem = 1;
type = t;
Initializer *aa = NULL;
t = t->toBasetype();
switch (t->ty)
{
case Tpointer:
case Tsarray:
case Tarray:
break;
@@ -402,15 +400,27 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
break;
case Taarray:
// was actually an associative array literal
aa = new ExpInitializer(loc, toAssocArrayLiteral());
return aa->semantic(sc, t, needInterpret);
case Tstruct: // consider implicit constructor call
{
Expression *e;
if (t->ty == Taarray || isAssociativeArray())
e = toAssocArrayLiteral();
else
e = toExpression();
ExpInitializer *ei = new ExpInitializer(e->loc, e);
return ei->semantic(sc, t, needInterpret);
}
case Tpointer:
if (t->nextOf()->ty != Tfunction)
break;
default:
error(loc, "cannot use array to initialize %s", type->toChars());
error(loc, "cannot use array to initialize %s", t->toChars());
goto Lerr;
}
type = t;
length = 0;
for (size_t i = 0; i < index.dim; i++)
{
@@ -422,7 +432,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
sc = sc->endCTFE();
idx = idx->ctfeInterpret();
index[i] = idx;
length = idx->toInteger();
length = (size_t)idx->toInteger();
if (idx->op == TOKerror)
errors = true;
}
@@ -509,7 +519,7 @@ Expression *ArrayInitializer::toExpression(Type *tx)
switch (t->ty)
{
case Tsarray:
edim = ((TypeSArray *)t)->dim->toInteger();
edim = (size_t)((TypeSArray *)t)->dim->toInteger();
break;
case Tpointer:
@@ -529,7 +539,7 @@ Expression *ArrayInitializer::toExpression(Type *tx)
if (index[i])
{
if (index[i]->op == TOKint64)
j = index[i]->toInteger();
j = (size_t)index[i]->toInteger();
else
goto Lno;
}
@@ -544,7 +554,7 @@ Expression *ArrayInitializer::toExpression(Type *tx)
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index[i])
j = (index[i])->toInteger();
j = (size_t)(index[i])->toInteger();
assert(j < edim);
Initializer *iz = value[i];
if (!iz)
@@ -808,7 +818,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
exp = resolveProperties(sc, exp);
if (needInterpret) sc = sc->endCTFE();
if (exp->op == TOKerror)
return this;
return new ErrorInitializer();
int olderrors = global.errors;
if (needInterpret)
@@ -966,7 +976,7 @@ Expression *ExpInitializer::toExpression(Type *t)
if (tb->ty == Tsarray && exp->implicitConvTo(tb->nextOf()))
{
TypeSArray *tsa = (TypeSArray *)tb;
size_t d = tsa->dim->toInteger();
size_t d = (size_t)tsa->dim->toInteger();
Expressions *elements = new Expressions();
elements->setDim(d);
for (size_t i = 0; i < d; i++)
+237 -152
View File
@@ -156,12 +156,10 @@ int ReturnStatement::inlineCost(InlineCostState *ics)
return expressionInlineCost(exp, ics);
}
#if DMDV2
int ImportStatement::inlineCost(InlineCostState *ics)
{
return 0;
}
#endif
int ForStatement::inlineCost(InlineCostState *ics)
{
@@ -253,10 +251,8 @@ int ThisExp::inlineCost3(InlineCostState *ics)
int StructLiteralExp::inlineCost3(InlineCostState *ics)
{
//printf("StructLiteralExp::inlineCost3() %s\n", toChars());
#if DMDV2
if (sd->isNested())
return COST_MAX;
#endif
return 1;
}
@@ -309,10 +305,8 @@ int DeclarationExp::inlineCost3(InlineCostState *ics)
return COST_MAX;
cost += 1;
#if DMDV2
if (vd->edtor) // if destructor required
return COST_MAX; // needs work to make this work
#endif
// Scan initializer (vd->init)
if (vd->init)
{
@@ -332,9 +326,7 @@ int DeclarationExp::inlineCost3(InlineCostState *ics)
declaration->isClassDeclaration() ||
declaration->isFuncDeclaration() ||
declaration->isTypedefDeclaration() ||
#if DMDV2
declaration->isAttribDeclaration() ||
#endif
declaration->isTemplateMixin())
return COST_MAX;
@@ -364,13 +356,15 @@ int CallExp::inlineCost3(InlineCostState *ics)
struct InlineDoState
{
// inline context
VarDeclaration *vthis;
Dsymbols from; // old Dsymbols
Dsymbols to; // parallel array of new Dsymbols
Dsymbol *parent; // new parent
FuncDeclaration *fd; // function being inlined (old parent)
// inline result
bool foundReturn;
};
/* -------------------------------------------------------------------- */
Statement *Statement::doInlineStatement(InlineDoState *ids)
@@ -397,20 +391,7 @@ Statement *CompoundStatement::doInlineStatement(InlineDoState *ids)
if (s)
{
as->push(s->doInlineStatement(ids));
if (s->isReturnStatement())
break;
/* Check for:
* if (condition)
* return exp1;
* else
* return exp2;
*/
IfStatement *ifs = s->isIfStatement();
if (ifs && ifs->elsebody && ifs->ifbody &&
ifs->ifbody->isReturnStatement() &&
ifs->elsebody->isReturnStatement()
)
if (ids->foundReturn)
break;
}
else
@@ -429,7 +410,7 @@ Statement *UnrolledLoopStatement::doInlineStatement(InlineDoState *ids)
if (s)
{
as->push(s->doInlineStatement(ids));
if (s->isReturnStatement())
if (ids->foundReturn)
break;
}
else
@@ -450,7 +431,11 @@ Statement *IfStatement::doInlineStatement(InlineDoState *ids)
Expression *condition = this->condition ? this->condition->doInline(ids) : NULL;
Statement *ifbody = this->ifbody ? this->ifbody->doInlineStatement(ids) : NULL;
bool bodyReturn = ids->foundReturn;
ids->foundReturn = false;
Statement *elsebody = this->elsebody ? this->elsebody->doInlineStatement(ids) : NULL;
ids->foundReturn = ids->foundReturn && bodyReturn;
return new IfStatement(loc, arg, condition, ifbody, elsebody);
}
@@ -458,15 +443,14 @@ Statement *IfStatement::doInlineStatement(InlineDoState *ids)
Statement *ReturnStatement::doInlineStatement(InlineDoState *ids)
{
//printf("ReturnStatement::doInlineStatement() '%s'\n", exp ? exp->toChars() : "");
ids->foundReturn = true;
return new ReturnStatement(loc, exp ? exp->doInline(ids) : NULL);
}
#if DMDV2
Statement *ImportStatement::doInlineStatement(InlineDoState *ids)
{
return NULL;
}
#endif
Statement *ForStatement::doInlineStatement(InlineDoState *ids)
{
@@ -507,20 +491,7 @@ Expression *CompoundStatement::doInline(InlineDoState *ids)
{
Expression *e2 = s->doInline(ids);
e = Expression::combine(e, e2);
if (s->isReturnStatement())
break;
/* Check for:
* if (condition)
* return exp1;
* else
* return exp2;
*/
IfStatement *ifs = s->isIfStatement();
if (ifs && ifs->elsebody && ifs->ifbody &&
ifs->ifbody->isReturnStatement() &&
ifs->elsebody->isReturnStatement()
)
if (ids->foundReturn)
break;
}
@@ -539,7 +510,7 @@ Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
{
Expression *e2 = s->doInline(ids);
e = Expression::combine(e, e2);
if (s->isReturnStatement())
if (ids->foundReturn)
break;
}
}
@@ -562,9 +533,13 @@ Expression *IfStatement::doInline(InlineDoState *ids)
econd = condition->doInline(ids);
assert(econd);
if (ifbody)
{
e1 = ifbody->doInline(ids);
}
else
e1 = NULL;
bool bodyReturn = ids->foundReturn;
ids->foundReturn = false;
if (elsebody)
e2 = elsebody->doInline(ids);
else
@@ -573,6 +548,12 @@ Expression *IfStatement::doInline(InlineDoState *ids)
{
e = new CondExp(econd->loc, econd, e1, e2);
e->type = e1->type;
if (e->type->ty == Ttuple)
{
e1->type = Type::tvoid;
e2->type = Type::tvoid;
e->type = Type::tvoid;
}
}
else if (e1)
{
@@ -588,21 +569,21 @@ Expression *IfStatement::doInline(InlineDoState *ids)
{
e = econd;
}
ids->foundReturn = ids->foundReturn && bodyReturn;
return e;
}
Expression *ReturnStatement::doInline(InlineDoState *ids)
{
//printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
ids->foundReturn = true;
return exp ? exp->doInline(ids) : NULL;
}
#if DMDV2
Expression *ImportStatement::doInline(InlineDoState *ids)
{
return NULL;
}
#endif
/* --------------------------------------------------------------- */
@@ -643,7 +624,6 @@ Expression *SymOffExp::doInline(InlineDoState *ids)
if (var == ids->from[i])
{
SymOffExp *se = (SymOffExp *)copy();
se->var = (Declaration *)ids->to[i];
return se;
}
@@ -659,7 +639,6 @@ Expression *VarExp::doInline(InlineDoState *ids)
if (var == ids->from[i])
{
VarExp *ve = (VarExp *)copy();
ve->var = (Declaration *)ids->to[i];
return ve;
}
@@ -755,11 +734,9 @@ Expression *SuperExp::doInline(InlineDoState *ids)
}
Expression *DeclarationExp::doInline(InlineDoState *ids)
{ DeclarationExp *de = (DeclarationExp *)copy();
VarDeclaration *vd;
{
//printf("DeclarationExp::doInline(%s)\n", toChars());
vd = declaration->isVarDeclaration();
VarDeclaration *vd = declaration->isVarDeclaration();
if (vd)
{
#if 0
@@ -780,9 +757,33 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
else
{
VarDeclaration *vto;
if (ids->fd && vd == ids->fd->nrvo_var)
{
for (size_t i = 0; i < ids->from.dim; i++)
{
if (vd == ids->from[i])
{
vto = (VarDeclaration *)ids->to[i];
if ((vd->storage_class & STCref) == 0 &&
(vto->storage_class & STCref))
{
Expression *e;
if (vd->init && !vd->init->isVoidInitializer())
{
e = vd->init->toExpression();
assert(e);
e = e->doInline(ids);
}
else
e = new IntegerExp(vd->init->loc, 0, Type::tint32);
return e;
}
goto L1;
}
}
}
vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
memcpy((void*)vto, (void*)vd, sizeof(VarDeclaration));
memcpy((void *)vto, (void *)vd, sizeof(VarDeclaration));
vto->parent = ids->parent;
#if IN_DMD
vto->csym = NULL;
@@ -792,6 +793,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
ids->from.push(vd);
ids->to.push(vto);
L1:
if (vd->init)
{
if (vd->init->isVoidInitializer())
@@ -805,13 +807,15 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
vto->init = new ExpInitializer(e->loc, e->doInline(ids));
}
}
DeclarationExp *de = (DeclarationExp *)copy();
de->declaration = (Dsymbol *) (void *)vto;
return de;
}
}
/* This needs work, like DeclarationExp::toElem(), if we are
* to handle TemplateMixin's. For now, we just don't inline them.
*/
return de;
return Expression::doInline(ids);
}
Expression *NewExp::doInline(InlineDoState *ids)
@@ -1051,7 +1055,7 @@ Statement *ExpStatement::inlineScan(InlineScanState *iss)
if (fd && fd != iss->fd && fd->canInline(0, 0, 1))
{
Statement *s;
fd->expandInline(iss, NULL, ce->arguments, &s);
fd->expandInline(iss, NULL, NULL, ce->arguments, &s);
return s;
}
}
@@ -1126,7 +1130,6 @@ Statement *ForeachStatement::inlineScan(InlineScanState *iss)
}
#if DMDV2
Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
{
lwr = lwr->inlineScan(iss);
@@ -1135,7 +1138,6 @@ Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
body = body->inlineScan(iss);
return this;
}
#endif
Statement *IfStatement::inlineScan(InlineScanState *iss)
@@ -1281,7 +1283,7 @@ Expression *Expression::inlineScan(InlineScanState *iss)
return this;
}
void scanVar(Dsymbol *s, InlineScanState *iss)
Expression *scanVar(Dsymbol *s, InlineScanState *iss)
{
//printf("scanVar(%s %s)\n", s->kind(), s->toPrettyChars());
VarDeclaration *vd = s->isVarDeclaration();
@@ -1291,47 +1293,20 @@ void scanVar(Dsymbol *s, InlineScanState *iss)
if (td)
{
for (size_t i = 0; i < td->objects->dim; i++)
{ DsymbolExp *se = (DsymbolExp *)(*td->objects)[i];
{
DsymbolExp *se = (DsymbolExp *)(*td->objects)[i];
assert(se->op == TOKdsymbol);
scanVar(se->s, iss);
scanVar(se->s, iss); // TODO
}
}
else
else if (vd->init)
{
// Scan initializer (vd->init)
if (vd->init)
if (ExpInitializer *ie = vd->init->isExpInitializer())
{
ExpInitializer *ie = vd->init->isExpInitializer();
if (ie)
{
#if DMDV2
if (vd->type)
{ Type *tb = vd->type->toBasetype();
if (tb->ty == Tstruct)
{ StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->cpctor)
{ /* The problem here is that if the initializer is a
* function call that returns a struct S with a cpctor:
* S s = foo();
* the postblit is done by the return statement in foo()
* in s2ir.c, the intermediate code generator.
* But, if foo() is inlined and now the code looks like:
* S s = x;
* the postblit is not there, because such assignments
* are rewritten as s.cpctor(&x) by the front end.
* So, the inlining won't get the postblit called.
* Work around by not inlining these cases.
* A proper fix would be to move all the postblit
* additions to the front end.
*/
return;
}
}
}
#endif
ie->exp = ie->exp->inlineScan(iss);
}
Expression *e = ie->exp->inlineScan(iss);
if (vd->init != ie) // DeclareExp with vd appears in e
return e;
ie->exp = e;
}
}
}
@@ -1339,13 +1314,14 @@ void scanVar(Dsymbol *s, InlineScanState *iss)
{
s->inlineScan();
}
return NULL;
}
Expression *DeclarationExp::inlineScan(InlineScanState *iss)
{
//printf("DeclarationExp::inlineScan()\n");
scanVar(declaration, iss);
return this;
Expression *e = scanVar(declaration, iss);
return e ? e : this;
}
Expression *UnaExp::inlineScan(InlineScanState *iss)
@@ -1369,9 +1345,51 @@ Expression *BinExp::inlineScan(InlineScanState *iss)
return this;
}
Expression *AssignExp::inlineScan(InlineScanState *iss)
{
if (op == TOKconstruct && e2->op == TOKcall)
{
CallExp *ce = (CallExp *)e2;
if (ce->f && ce->f->nrvo_var) // NRVO
{
if (e1->op == TOKvar)
{
/* Inlining:
* S s = foo(); // initializing by rvalue
* S s = S(1); // constrcutor call
*/
Declaration *d = ((VarExp *)e1)->var;
if (d->storage_class & (STCout | STCref)) // refinit
goto L1;
}
else
{
/* Inlining:
* this.field = foo(); // inside constructor
*/
e1 = e1->inlineScan(iss);
}
Expression *e = ce->inlineScan(iss, e1);
if (e != ce)
{
//printf("call with nrvo: %s ==> %s\n", toChars(), e->toChars());
return e;
}
}
}
L1:
return BinExp::inlineScan(iss);
}
Expression *CallExp::inlineScan(InlineScanState *iss)
{ Expression *e = this;
{
return inlineScan(iss, NULL);
}
Expression *CallExp::inlineScan(InlineScanState *iss, Expression *eret)
{
Expression *e = this;
//printf("CallExp::inlineScan()\n");
e1 = e1->inlineScan(iss);
@@ -1384,7 +1402,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
if (fd && fd != iss->fd && fd->canInline(0, 0, 0))
{
e = fd->expandInline(iss, NULL, arguments, NULL);
e = fd->expandInline(iss, eret, NULL, arguments, NULL);
}
}
else if (e1->op == TOKdotvar)
@@ -1404,10 +1422,12 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
;
}
else
e = fd->expandInline(iss, dve->e1, arguments, NULL);
e = fd->expandInline(iss, eret, dve->e1, arguments, NULL);
}
}
if (e && type->ty != Tvoid)
e->type = type;
return e;
}
@@ -1680,12 +1700,13 @@ Lno:
return 0;
}
Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps)
Expression *FuncDeclaration::expandInline(InlineScanState *iss,
Expression *eret, Expression *ethis, Expressions *arguments, Statement **ps)
{
InlineDoState ids;
DeclarationExp *de;
Expression *e = NULL;
Statements *as = NULL;
TypeFunction *tf = (TypeFunction*)type;
#if LOG || CANINLINE_LOG
printf("FuncDeclaration::expandInline('%s')\n", toChars());
@@ -1698,6 +1719,38 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
if (ps)
as = new Statements();
VarDeclaration *vret = NULL;
if (eret)
{
if (eret->op == TOKvar)
{
vret = ((VarExp *)eret)->var->isVarDeclaration();
assert(!(vret->storage_class & (STCout | STCref)));
}
else
{
/* Inlining:
* this.field = foo(); // inside constructor
*/
vret = new VarDeclaration(loc, eret->type, Lexer::uniqueId("_satmp"), NULL);
vret->storage_class |= STCtemp | STCforeach | STCref;
vret->linkage = LINKd;
vret->parent = iss->fd;
Expression *de;
de = new DeclarationExp(loc, vret);
de->type = Type::tvoid;
e = Expression::combine(e, de);
Expression *ex;
ex = new VarExp(loc, vret);
ex->type = vret->type;
ex = new ConstructExp(loc, ex, eret);
ex->type = vret->type;
e = Expression::combine(e, ex);
}
}
// Set up vthis
if (ethis)
{
@@ -1737,12 +1790,31 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
// Set up parameters
if (ethis)
{
e = new DeclarationExp(Loc(), ids.vthis);
e->type = Type::tvoid;
if (as)
as->push(new ExpStatement(e->loc, e));
Expression *de = new DeclarationExp(Loc(), ids.vthis);
de->type = Type::tvoid;
e = Expression::combine(e, de);
}
if (!ps && nrvo_var)
{
if (vret)
{
ids.from.push(nrvo_var);
ids.to.push(vret);
}
else
{
Identifier* tmp = Identifier::generateId("__nrvoretval");
VarDeclaration* vd = new VarDeclaration(loc, nrvo_var->type, tmp, NULL);
assert(!tf->isref);
vd->storage_class = STCtemp | STCrvalue;
vd->linkage = tf->linkage;
vd->parent = iss->fd;
ids.from.push(nrvo_var);
ids.to.push(vd);
}
}
if (arguments && arguments->dim)
{
assert(parameters->dim == arguments->dim);
@@ -1758,7 +1830,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
ei = new ExpInitializer(arg->loc, arg);
vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref);
vto->storage_class |= vfrom->storage_class & (STCtemp | STCin | STCout | STClazy | STCref);
vto->linkage = vfrom->linkage;
vto->parent = iss->fd;
//printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
@@ -1770,25 +1842,24 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
ei->exp = new ConstructExp(vto->loc, ve, arg);
ei->exp->type = ve->type;
//ve->type->print();
//arg->type->print();
//ei->exp->print();
//ve->type->print();
//arg->type->print();
//ei->exp->print();
ids.from.push(vfrom);
ids.to.push(vto);
de = new DeclarationExp(Loc(), vto);
DeclarationExp *de = new DeclarationExp(Loc(), vto);
de->type = Type::tvoid;
if (as)
as->push(new ExpStatement(Loc(), de));
else
e = Expression::combine(e, de);
e = Expression::combine(e, de);
}
}
if (ps)
{
if (e)
as->push(new ExpStatement(Loc(), e));
inlineNest++;
Statement *s = fbody->doInlineStatement(&ids);
as->push(s);
@@ -1804,55 +1875,69 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
//eb->type->print();
//eb->print();
//eb->dump(0);
// Bugzilla 11322:
if (tf->isref)
e = e->toLvalue(NULL, NULL);
/* There's a problem if what the function returns is used subsequently as an
* lvalue, as in a struct return that is then used as a 'this'.
* If we take the address of the return value, we will be taking the address
* of the original, not the copy. Fix this by assigning the return value to
* a temporary, then returning the temporary. If the temporary is used as an
* lvalue, it will work.
* This only happens with struct returns.
* See Bugzilla 2127 for an example.
*
* On constructor call making __inlineretval is merely redundant, because
* the returned reference is exactly same as vthis, and the 'this' variable
* already exists at the caller side.
*/
if (tf->next->ty == Tstruct && !nrvo_var && !isCtorDeclaration())
{
/* Generate a new variable to hold the result and initialize it with the
* inlined body of the function:
* tret __inlineretval = e;
*/
ExpInitializer* ei = new ExpInitializer(loc, e);
Identifier* tmp = Identifier::generateId("__inlineretval");
VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei);
vd->storage_class = (tf->isref ? STCref : 0) | STCtemp | STCrvalue;
vd->linkage = tf->linkage;
vd->parent = iss->fd;
VarExp *ve = new VarExp(loc, vd);
ve->type = tf->next;
ei->exp = new ConstructExp(loc, ve, e);
ei->exp->type = ve->type;
DeclarationExp* de = new DeclarationExp(Loc(), vd);
de->type = Type::tvoid;
// Chain the two together:
// ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval
e = Expression::combine(de, ve);
//fprintf(stderr, "CallExp::inlineScan: e = "); e->print();
}
}
//printf("%s->expandInline = { %s }\n", toChars(), e->toChars());
/* There's a problem if what the function returns is used subsequently as an
* lvalue, as in a struct return that is then used as a 'this'.
* If we take the address of the return value, we will be taking the address
* of the original, not the copy. Fix this by assigning the return value to
* a temporary, then returning the temporary. If the temporary is used as an
* lvalue, it will work.
* This only happens with struct returns.
* See Bugzilla 2127 for an example.
*/
TypeFunction *tf = (TypeFunction*)type;
if (!ps && tf->next->ty == Tstruct)
{
/* Generate a new variable to hold the result and initialize it with the
* inlined body of the function:
* tret __inlineretval = e;
*/
ExpInitializer* ei = new ExpInitializer(loc, e);
Identifier* tmp = Identifier::generateId("__inlineretval");
VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei);
vd->storage_class = (tf->isref ? STCref : 0) | STCtemp;
vd->linkage = tf->linkage;
vd->parent = iss->fd;
VarExp *ve = new VarExp(loc, vd);
ve->type = tf->next;
ei->exp = new ConstructExp(loc, ve, e);
ei->exp->type = ve->type;
DeclarationExp* de = new DeclarationExp(Loc(), vd);
de->type = Type::tvoid;
// Chain the two together:
// ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval
e = Expression::combine(de, ve);
//fprintf(stderr, "CallExp::inlineScan: e = "); e->print();
}
// Need to reevaluate whether parent can now be inlined
// in expressions, as we might have inlined statements
iss->fd->inlineStatusExp = ILSuninitialized;
return e;
}
void UnitTestDeclaration::inlineScan()
{
if (global.params.useUnitTests)
{
FuncDeclaration::inlineScan();
}
}
/****************************************************
* Perform the "inline copying" of a default argument for a function parameter.
+207 -85
View File
@@ -306,7 +306,7 @@ int CompiledCtfeFunction::walkAllVars(Expression *e, void *_this)
if (global.gag && ccf->func)
return 1;
printf("CTFE: ErrorExp in %s\n", ccf->func ? ccf->func->loc.toChars() : ccf->callingloc.toChars());
e->error("CTFE internal error: ErrorExp in %s\n", ccf->func ? ccf->func->loc.toChars() : ccf->callingloc.toChars());
assert(0);
}
if (e->op == TOKdeclaration)
@@ -570,11 +570,7 @@ void TryCatchStatement::ctfeCompile(CompiledCtfeFunction *ccf)
body->ctfeCompile(ccf);
for (size_t i = 0; i < catches->dim; i++)
{
#if DMDV1
Catch *ca = (Catch *)catches->data[i];
#else
Catch *ca = catches->tdata()[i];
#endif
Catch *ca = (*catches)[i];
if (ca->var)
ccf->onDeclaration(ca->var);
if (ca->handler)
@@ -958,6 +954,12 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
#endif
}
if (istatex.start)
{
error("CTFE internal error: failed to resume at statement %s", istatex.start->toChars());
return EXP_CANT_INTERPRET;
}
/* This is how we deal with a recursive statement AST
* that has arbitrary goto statements in it.
* Bubble up a 'result' which is the target of the goto
@@ -1001,13 +1003,6 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
/******************************** Statement ***************************/
#define START() \
if (istate->start) \
{ if (istate->start != this) \
return NULL; \
istate->start = NULL; \
}
/***********************************
* Interpret the statement.
* Returns:
@@ -1021,7 +1016,12 @@ Expression *Statement::interpret(InterState *istate)
#if LOG
printf("%s Statement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
error("Statement %s cannot be interpreted at compile time", this->toChars());
return EXP_CANT_INTERPRET;
}
@@ -1031,7 +1031,12 @@ Expression *ExpStatement::interpret(InterState *istate)
#if LOG
printf("%s ExpStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : "");
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
if (exp)
{
Expression *e = exp->interpret(istate, ctfeNeedNothing);
@@ -1140,7 +1145,7 @@ Expression *IfStatement::interpret(InterState *istate)
{
if (isTrueBool(e))
e = ifbody ? ifbody->interpret(istate) : NULL;
else if (e->isBool(FALSE))
else if (e->isBool(false))
e = elsebody ? elsebody->interpret(istate) : NULL;
else
{
@@ -1349,7 +1354,12 @@ Expression *ReturnStatement::interpret(InterState *istate)
#if LOG
printf("%s ReturnStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : "");
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
if (!exp)
return EXP_VOID_INTERPRET;
assert(istate && istate->fd && istate->fd->type);
@@ -1410,7 +1420,12 @@ Expression *BreakStatement::interpret(InterState *istate)
#if LOG
printf("%s BreakStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
if (ident)
{
LabelDsymbol *label = istate->fd->searchLabel(ident);
@@ -1440,7 +1455,12 @@ Expression *ContinueStatement::interpret(InterState *istate)
#if LOG
printf("%s ContinueStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
if (ident)
{
LabelDsymbol *label = istate->fd->searchLabel(ident);
@@ -1513,7 +1533,7 @@ Expression *DoStatement::interpret(InterState *istate)
if (isTrueBool(e))
{
}
else if (e->isBool(FALSE))
else if (e->isBool(false))
{ e = NULL;
break;
}
@@ -1550,7 +1570,7 @@ Expression *ForStatement::interpret(InterState *istate)
{ e = EXP_CANT_INTERPRET;
break;
}
if (e->isBool(FALSE))
if (e->isBool(false))
{ e = NULL;
break;
}
@@ -1704,7 +1724,12 @@ Expression *GotoStatement::interpret(InterState *istate)
#if LOG
printf("%s GotoStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
assert(label && label->statement);
istate->gotoTarget = label->statement;
return EXP_GOTO_INTERPRET;
@@ -1715,7 +1740,12 @@ Expression *GotoCaseStatement::interpret(InterState *istate)
#if LOG
printf("%s GotoCaseStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
assert(cs);
istate->gotoTarget = cs;
return EXP_GOTO_INTERPRET;
@@ -1726,7 +1756,12 @@ Expression *GotoDefaultStatement::interpret(InterState *istate)
#if LOG
printf("%s GotoDefaultStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
assert(sw && sw->sdefault);
istate->gotoTarget = sw->sdefault;
return EXP_GOTO_INTERPRET;
@@ -1748,7 +1783,22 @@ Expression *TryCatchStatement::interpret(InterState *istate)
#if LOG
printf("%s TryCatchStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start == this)
istate->start = NULL;
if (istate->start)
{
Expression *e = NULL;
if (body)
e = body->interpret(istate);
for (size_t i = 0; !e && istate->start && i < catches->dim; i++)
{
Catch *ca = (*catches)[i];
if (ca->handler)
e = ca->handler->interpret(istate);
}
return e;
}
Expression *e = body ? body->interpret(istate) : NULL;
if (e == EXP_CANT_INTERPRET)
return e;
@@ -1760,21 +1810,36 @@ Expression *TryCatchStatement::interpret(InterState *istate)
// Search for an appropriate catch clause.
for (size_t i = 0; i < catches->dim; i++)
{
#if DMDV1
Catch *ca = (Catch *)catches->data[i];
#else
Catch *ca = (*catches)[i];
#endif
Type *catype = ca->type;
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
{ // Execute the handler
{
// Execute the handler
if (ca->var)
{
ctfeStack.push(ca->var);
ca->var->setValue(ex->thrown);
}
return ca->handler ? ca->handler->interpret(istate) : NULL;
if (ca->handler)
{
e = ca->handler->interpret(istate);
if (e == EXP_GOTO_INTERPRET)
{
InterState istatex = *istate;
istatex.start = istate->gotoTarget; // set starting statement
istatex.gotoTarget = NULL;
Expression *eh = ca->handler->interpret(&istatex);
if (!istatex.start)
{
istate->gotoTarget = NULL;
e = eh;
}
}
}
else
e = NULL;
return e;
}
}
return e;
@@ -1820,7 +1885,18 @@ Expression *TryFinallyStatement::interpret(InterState *istate)
#if LOG
printf("%s TryFinallyStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start == this)
istate->start = NULL;
if (istate->start)
{
Expression *e = NULL;
if (body)
e = body->interpret(istate);
// Jump into/out from finalbody is disabled in semantic analysis.
// and jump inside will be handled by the ScopeStatement == finalbody.
return e;
}
Expression *e = body ? body->interpret(istate) : NULL;
if (e == EXP_CANT_INTERPRET)
return e;
@@ -1842,7 +1918,12 @@ Expression *ThrowStatement::interpret(InterState *istate)
#if LOG
printf("%s ThrowStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
Expression *e = exp->interpret(istate);
if (exceptionOrCantInterpret(e))
return e;
@@ -1866,7 +1947,12 @@ Expression *WithStatement::interpret(InterState *istate)
if (exp->op == TOKimport || exp->op == TOKtype)
return body ? body->interpret(istate) : EXP_VOID_INTERPRET;
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
Expression *e = exp->interpret(istate);
if (exceptionOrCantInterpret(e))
return e;
@@ -1877,7 +1963,24 @@ Expression *WithStatement::interpret(InterState *istate)
}
ctfeStack.push(wthis);
wthis->setValue(e);
e = body ? body->interpret(istate) : EXP_VOID_INTERPRET;
if (body)
{
e = body->interpret(istate);
if (e == EXP_GOTO_INTERPRET)
{
InterState istatex = *istate;
istatex.start = istate->gotoTarget; // set starting statement
istatex.gotoTarget = NULL;
Expression *ex = body->interpret(&istatex);
if (!istatex.start)
{
istate->gotoTarget = NULL;
e = ex;
}
}
}
else
e = EXP_VOID_INTERPRET;
ctfeStack.pop(wthis);
return e;
}
@@ -1887,7 +1990,12 @@ Expression *AsmStatement::interpret(InterState *istate)
#if LOG
printf("%s AsmStatement::interpret()\n", loc.toChars());
#endif
START()
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
error("asm statements cannot be interpreted at compile time");
return EXP_CANT_INTERPRET;
}
@@ -1898,7 +2006,12 @@ Expression *ImportStatement::interpret(InterState *istate)
#if LOG
printf("ImportStatement::interpret()\n");
#endif
START();
if (istate->start)
{ if (istate->start != this)
return NULL;
istate->start = NULL;
}
;
return NULL;
}
#endif
@@ -2432,11 +2545,11 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
}
else if (s->isTupleDeclaration() && !v->init)
e = NULL;
else if (v->isStatic() && !v->init)
else if (v->isStatic())
e = NULL; // Just ignore static variables which aren't read or written yet
else
{
error("Static variable %s cannot be modified at compile time", v->toChars());
error("Variable %s cannot be modified at compile time", v->toChars());
e = EXP_CANT_INTERPRET;
}
}
@@ -2779,7 +2892,7 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is
|| elemType->ty == Tdchar)
return createBlockDuplicatedStringLiteral(loc, newtype,
(unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
len, elemType->size());
len, (unsigned char)elemType->size());
return createBlockDuplicatedArrayLiteral(loc, newtype,
elemType->defaultInitLiteral(loc),
len);
@@ -3207,8 +3320,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (op == TOKconstruct && this->e1->op==TOKvar
&& ((VarExp*)this->e1)->var->storage_class & STCref)
{
wantRef = true;
wantLvalueRef = true;
wantRef = true;
wantLvalueRef = true;
}
if (fp)
@@ -3353,8 +3466,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
returnValue = newval;
if (e1->op == TOKarraylength)
{
size_t oldlen = oldval->toInteger();
size_t newlen = newval->toInteger();
size_t oldlen = (size_t)oldval->toInteger();
size_t newlen = (size_t)newval->toInteger();
if (oldlen == newlen) // no change required -- we're done!
return returnValue;
// Now change the assignment from arr.length = n into arr = newval
@@ -3894,9 +4007,9 @@ bool interpretAssignToIndex(InterState *istate, Loc loc,
if (existingAE)
{
if (newval->op == TOKstructliteral)
assignInPlace((*existingAE->elements)[indexToModify], newval);
assignInPlace((*existingAE->elements)[(size_t)indexToModify], newval);
else
(*existingAE->elements)[indexToModify] = newval;
(*existingAE->elements)[(size_t)indexToModify] = newval;
return true;
}
if (existingSE)
@@ -3907,12 +4020,12 @@ bool interpretAssignToIndex(InterState *istate, Loc loc,
originalExp->error("cannot modify read-only string literal %s", ie->e1->toChars());
return false;
}
unsigned value = newval->toInteger();
dinteger_t value = newval->toInteger();
switch (existingSE->sz)
{
case 1: s[indexToModify] = value; break;
case 2: ((unsigned short *)s)[indexToModify] = value; break;
case 4: ((unsigned *)s)[indexToModify] = value; break;
case 1: s[(size_t)indexToModify] = (utf8_t)value; break;
case 2: ((unsigned short *)s)[(size_t)indexToModify] = (unsigned short)value; break;
case 4: ((unsigned *)s)[(size_t)indexToModify] = (unsigned)value; break;
default:
assert(0);
break;
@@ -4008,9 +4121,9 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc,
if (exceptionOrCantInterpret(lower))
return lower;
size_t dim = dollar;
size_t upperbound = upper ? upper->toInteger() : dim;
int lowerbound = lower ? lower->toInteger() : 0;
unsigned dim = (unsigned)dollar;
size_t upperbound = (size_t)(upper ? upper->toInteger() : dim);
int lowerbound = (int)(lower ? lower->toInteger() : 0);
if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim)))
{
@@ -4137,13 +4250,13 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc,
Type *elemtype = existingAE->type->nextOf();
for (size_t j = 0; j < newelems->dim; j++)
{
(*oldelems)[j + firstIndex] = paintTypeOntoLiteral(elemtype, (*newelems)[j]);
(*oldelems)[(size_t)(j + firstIndex)] = paintTypeOntoLiteral(elemtype, (*newelems)[j]);
}
return newval;
}
else if (newval->op == TOKstring && existingSE)
{
sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, firstIndex);
sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, (size_t)firstIndex);
return newval;
}
else if (newval->op == TOKstring && existingAE
@@ -4151,27 +4264,27 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc,
{ /* Mixed slice: it was initialized as an array literal of chars.
* Now a slice of it is being set with a string.
*/
sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, firstIndex);
sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, (size_t)firstIndex);
return newval;
}
else if (newval->op == TOKarrayliteral && existingSE)
{ /* Mixed slice: it was initialized as a string literal.
* Now a slice of it is being set with an array literal.
*/
sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, firstIndex);
sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, (size_t)firstIndex);
return newval;
}
else if (existingSE)
{ // String literal block slice assign
unsigned value = newval->toInteger();
dinteger_t value = newval->toInteger();
utf8_t *s = (utf8_t *)existingSE->string;
for (size_t j = 0; j < upperbound-lowerbound; j++)
{
switch (existingSE->sz)
{
case 1: s[j+firstIndex] = value; break;
case 2: ((unsigned short *)s)[j+firstIndex] = value; break;
case 4: ((unsigned *)s)[j+firstIndex] = value; break;
case 1: s[(size_t)(j+firstIndex)] = (utf8_t)value; break;
case 2: ((unsigned short *)s)[(size_t)(j+firstIndex)] = (unsigned short)value; break;
case 4: ((unsigned *)s)[(size_t)(j+firstIndex)] = (unsigned)value; break;
default:
assert(0);
break;
@@ -4208,13 +4321,13 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc,
{
if (!directblk)
// Multidimensional array block assign
recursiveBlockAssign((ArrayLiteralExp *)(*w)[j+firstIndex], newval, wantRef);
recursiveBlockAssign((ArrayLiteralExp *)(*w)[(size_t)(j+firstIndex)], newval, wantRef);
else
{
if (wantRef || cow)
(*existingAE->elements)[j+firstIndex] = newval;
(*existingAE->elements)[(size_t)(j+firstIndex)] = newval;
else
assignInPlace((*existingAE->elements)[j+firstIndex], newval);
assignInPlace((*existingAE->elements)[(size_t)(j+firstIndex)], newval);
}
}
if (goal == ctfeNeedNothing)
@@ -4376,7 +4489,7 @@ Expression *BinExp::interpretFourPointerRelation(InterState *istate, CtfeGoal go
if ( !pointToSameMemoryBlock(agg1, agg2)
&& agg1->op != TOKnull && agg2->op != TOKnull)
{ // Here it is either CANT_INTERPRET,
// or an IsInside comparison returning FALSE.
// or an IsInside comparison returning false.
p3 = p3->interpret(istate);
if (p3 == EXP_CANT_INTERPRET)
return p3;
@@ -4463,7 +4576,7 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal)
int result;
if (e != EXP_CANT_INTERPRET)
{
if (e->isBool(FALSE))
if (e->isBool(false))
result = 0;
else if (isTrueBool(e))
{
@@ -4475,7 +4588,7 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal)
assert(type->ty == Tvoid);
return NULL;
}
if (e->isBool(FALSE))
if (e->isBool(false))
result = 0;
else if (isTrueBool(e))
result = 1;
@@ -4516,7 +4629,7 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal)
{
if (isTrueBool(e))
result = 1;
else if (e->isBool(FALSE))
else if (e->isBool(false))
{
e = e2->interpret(istate);
if (exceptionOrCantInterpret(e))
@@ -4529,7 +4642,7 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal)
}
if (e != EXP_CANT_INTERPRET)
{
if (e->isBool(FALSE))
if (e->isBool(false))
result = 0;
else if (isTrueBool(e))
result = 1;
@@ -4788,14 +4901,18 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
}
eresult = fd->interpret(istate, arguments, pthis);
if (eresult == EXP_CANT_INTERPRET)
{ // Print a stack trace.
{
// Print a stack trace.
if (!global.gag)
showCtfeBackTrace(istate, this, fd);
}
else if (eresult == EXP_VOID_INTERPRET)
;
else
{
eresult->type = type;
eresult->loc = loc;
}
return eresult;
}
@@ -4888,7 +5005,7 @@ Expression *CondExp::interpret(InterState *istate, CtfeGoal goal)
return e;
if (isTrueBool(e))
e = e1->interpret(istate, goal);
else if (e->isBool(FALSE))
else if (e->isBool(false))
e = e2->interpret(istate, goal);
else
{
@@ -5412,7 +5529,7 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
Expression *xx = NULL;
if (ie->e1->op == TOKarrayliteral && ie->e2->op == TOKint64)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)ie->e1;
uinteger_t indx = ie->e2->toInteger();
size_t indx = (size_t)ie->e2->toInteger();
if (indx < ale->elements->dim)
xx = (*ale->elements)[indx];
}
@@ -5528,7 +5645,7 @@ Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal)
if (isTrueBool(e1))
{
}
else if (e1->isBool(FALSE))
else if (e1->isBool(false))
{
if (msg)
{
@@ -5583,7 +5700,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
if (ex->op == TOKstructliteral)
{ StructLiteralExp *se = (StructLiteralExp *)ex;
dinteger_t offset = ae->e2->toInteger();
e = se->getField(type, offset);
e = se->getField(type, (unsigned)offset);
if (!e)
e = EXP_CANT_INTERPRET;
return e;
@@ -5591,16 +5708,17 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
}
e = Ptr(type, e1);
}
#if DMDV2
#else // this is required for D1, where structs return *this instead of 'this'.
else if (e1->op == TOKthis)
{
if (ctfeStack.getThis())
return ctfeStack.getThis()->interpret(istate);
}
#endif
else
{
#if DMDV2
#else // this is required for D1, where structs return *this instead of 'this'.
if (e1->op == TOKthis)
{
if (ctfeStack.getThis())
return ctfeStack.getThis()->interpret(istate);
goto Ldone;
}
#endif
// Check for .classinfo, which is lowered in the semantic pass into **(class).
if (e1->op == TOKstar && e1->type->ty == Tpointer && isTypeInfo_Class(e1->type->nextOf()))
{
@@ -5738,6 +5856,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
e = paintTypeOntoLiteral(type, e);
}
Ldone:
#if LOG
if (e == EXP_CANT_INTERPRET)
printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
@@ -6046,7 +6165,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
Type *charType = (*fd->parameters)[numParams-1]->type;
Type *indexType = numParams == 2 ? (*fd->parameters)[0]->type
: Type::tsize_t;
uinteger_t len = resolveArrayLength(str);
size_t len = (size_t)resolveArrayLength(str);
if (len == 0)
return new IntegerExp(deleg->loc, 0, indexType);
@@ -6086,7 +6205,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
{ // If it is an array literal, copy the code points into the buffer
size_t buflen = 1; // #code points in the buffer
size_t n = 1; // #code points in this char
size_t sz = ale->type->nextOf()->size();
size_t sz = (size_t)ale->type->nextOf()->size();
switch(sz)
{
@@ -6148,7 +6267,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
Expression * r = (*ale->elements)[indx];
assert(r->op == TOKint64);
rawvalue = ((IntegerExp *)r)->value;
rawvalue = (dchar_t)((IntegerExp *)r)->value;
n = 1;
}
break;
@@ -6303,7 +6422,10 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
}
e = eval_builtin(loc, b, &args);
if (!e)
{
error(loc, "cannot evaluate unimplemented builtin %s at compile time", fd->toChars());
e = EXP_CANT_INTERPRET;
}
}
}
-6
View File
@@ -807,9 +807,7 @@ void ConditionalDeclaration::toJson(JsonOut *json)
void ClassInfoDeclaration::toJson(JsonOut *json) { }
void TypeInfoDeclaration::toJson(JsonOut *json) { }
#if DMDV2
void PostBlitDeclaration::toJson(JsonOut *json) { }
#endif
void Declaration::toJson(JsonOut *json)
@@ -966,14 +964,10 @@ void TemplateDeclaration::toJson(JsonOut *json)
TemplateTypeParameter *type = s->isTemplateTypeParameter();
if (type)
{
#if DMDV2
if (s->isTemplateThisParameter())
json->property("kind", "this");
else
json->property("kind", "type");
#else
json->property("kind", "type");
#endif
json->property("type", "deco", type->specType);
json->property("default", "defaultDeco", type->defaultType);
+165 -237
View File
@@ -36,7 +36,7 @@
#include "id.h"
#include "module.h"
extern int HtmlNamedEntity(utf8_t *p, size_t length);
extern int HtmlNamedEntity(const utf8_t *p, size_t length);
#define LS 0x2028 // UTF line separator
#define PS 0x2029 // UTF paragraph separator
@@ -53,9 +53,9 @@ const int CMoctal = 0x1;
const int CMhex = 0x2;
const int CMidchar = 0x4;
inline bool isoctal (utf8_t c) { return cmtable[c] & CMoctal; }
inline bool ishex (utf8_t c) { return cmtable[c] & CMhex; }
inline bool isidchar(utf8_t c) { return cmtable[c] & CMidchar; }
inline bool isoctal (utf8_t c) { return (cmtable[c] & CMoctal) != 0; }
inline bool ishex (utf8_t c) { return (cmtable[c] & CMhex) != 0; }
inline bool isidchar(utf8_t c) { return (cmtable[c] & CMidchar) != 0; }
static void cmtable_init()
{
@@ -99,55 +99,55 @@ const char *Token::toChars()
{ const char *p;
static char buffer[3 + 3 * sizeof(float80value) + 1];
p = buffer;
p = &buffer[0];
switch (value)
{
case TOKint32v:
sprintf(buffer,"%d",int32value);
sprintf(&buffer[0],"%d",int32value);
break;
case TOKuns32v:
case TOKcharv:
case TOKwcharv:
case TOKdcharv:
sprintf(buffer,"%uU",uns32value);
sprintf(&buffer[0],"%uU",uns32value);
break;
case TOKint64v:
sprintf(buffer,"%lldL",(longlong)int64value);
sprintf(&buffer[0],"%lldL",(longlong)int64value);
break;
case TOKuns64v:
sprintf(buffer,"%lluUL",(ulonglong)uns64value);
sprintf(&buffer[0],"%lluUL",(ulonglong)uns64value);
break;
case TOKfloat32v:
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "f");
ld_sprint(&buffer[0], 'g', float80value);
strcat(&buffer[0], "f");
break;
case TOKfloat64v:
ld_sprint(buffer, 'g', float80value);
ld_sprint(&buffer[0], 'g', float80value);
break;
case TOKfloat80v:
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "L");
ld_sprint(&buffer[0], 'g', float80value);
strcat(&buffer[0], "L");
break;
case TOKimaginary32v:
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "fi");
ld_sprint(&buffer[0], 'g', float80value);
strcat(&buffer[0], "fi");
break;
case TOKimaginary64v:
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "i");
ld_sprint(&buffer[0], 'g', float80value);
strcat(&buffer[0], "i");
break;
case TOKimaginary80v:
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "Li");
ld_sprint(&buffer[0], 'g', float80value);
strcat(&buffer[0], "Li");
break;
case TOKstring:
@@ -208,8 +208,8 @@ const char *Token::toChars(TOK value)
p = tochars[value];
if (!p)
{ sprintf(buffer,"TOK%d",value);
p = buffer;
{ sprintf(&buffer[0],"TOK%d",value);
p = &buffer[0];
}
return p;
}
@@ -221,7 +221,7 @@ StringTable Lexer::stringtable;
OutBuffer Lexer::stringbuffer;
Lexer::Lexer(Module *mod,
utf8_t *base, size_t begoffset, size_t endoffset,
const utf8_t *base, size_t begoffset, size_t endoffset,
int doDocComment, int commentToken)
{
scanloc = Loc(mod, 1);
@@ -409,7 +409,7 @@ Token *Lexer::peekPastParen(Token *tk)
* 0 invalid
*/
int Lexer::isValidIdentifier(char *p)
int Lexer::isValidIdentifier(const char *p)
{
size_t len;
size_t idx;
@@ -503,7 +503,6 @@ void Lexer::scan(Token *t)
t->value = hexStringConstant(t);
return;
#if DMDV2
case 'q':
if (p[1] == '"')
{
@@ -519,16 +518,14 @@ void Lexer::scan(Token *t)
}
else
goto case_ident;
#endif
case '"':
t->value = escapeStringConstant(t,0);
return;
#if ! TEXTUAL_ASSEMBLY_OUT
case '\\': // escaped string literal
{ unsigned c;
utf8_t *pstart = p;
const utf8_t *pstart = p;
stringbuffer.reset();
do
@@ -555,21 +552,14 @@ void Lexer::scan(Token *t)
memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
t->postfix = 0;
t->value = TOKstring;
#if DMDV2
error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart);
#endif
return;
}
#endif
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
#if DMDV2
case 'p': /*case 'q': case 'r':*/ case 's': case 't':
#else
case 'p': case 'q': /*case 'r':*/ case 's': case 't':
#endif
case 'u': case 'v': case 'w': /*case 'x':*/ case 'y':
case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E':
@@ -588,7 +578,7 @@ void Lexer::scan(Token *t)
if (isidchar(c))
continue;
else if (c & 0x80)
{ utf8_t *s = p;
{ const utf8_t *s = p;
unsigned u = decodeUTF();
if (isUniAlpha(u))
continue;
@@ -617,28 +607,15 @@ void Lexer::scan(Token *t)
if (!initdone) // lazy evaluation
{
initdone = true;
time_t t;
::time(&t);
char *p = ctime(&t);
time_t ct;
::time(&ct);
char *p = ctime(&ct);
assert(p);
sprintf(date, "%.6s %.4s", p + 4, p + 20);
sprintf(time, "%.8s", p + 11);
sprintf(timestamp, "%.24s", p);
sprintf(&date[0], "%.6s %.4s", p + 4, p + 20);
sprintf(&time[0], "%.8s", p + 11);
sprintf(&timestamp[0], "%.24s", p);
}
#if DMDV1
if (mod && id == Id::FILE)
{
t->ustring = (utf8_t *)(loc.filename ? loc.filename : mod->ident->toChars());
goto Lstr;
}
else if (mod && id == Id::LINE)
{
t->value = TOKint64v;
t->uns64value = scanloc.linnum;
}
else
#endif
if (id == Id::DATE)
{
t->ustring = (utf8_t *)date;
@@ -669,7 +646,7 @@ void Lexer::scan(Token *t)
for (const char *p = global.version + 1; 1; p++)
{
char c = *p;
c = *p;
if (isdigit((utf8_t)c))
minor = minor * 10 + c - '0';
else if (c == '.')
@@ -686,7 +663,6 @@ void Lexer::scan(Token *t)
t->value = TOKint64v;
t->uns64value = major * 1000 + minor;
}
#if DMDV2
else if (id == Id::EOFX)
{
t->value = TOKeof;
@@ -694,7 +670,6 @@ void Lexer::scan(Token *t)
while (!(*p == 0 || *p == 0x1A))
p++;
}
#endif
}
//printf("t->value = %d\n",t->value);
return;
@@ -962,12 +937,6 @@ void Lexer::scan(Token *t)
{ p++;
t->value = TOKminass;
}
#if 0
else if (*p == '>')
{ p++;
t->value = TOKarrow;
}
#endif
else if (*p == '-')
{ p++;
t->value = TOKminusminus;
@@ -1089,12 +1058,10 @@ void Lexer::scan(Token *t)
{ p++;
t->value = TOKequal; // ==
}
#if DMDV2
else if (*p == '>')
{ p++;
t->value = TOKgoesto; // =>
}
#endif
else
t->value = TOKassign; // =
return;
@@ -1109,7 +1076,6 @@ void Lexer::scan(Token *t)
t->value = TOKtilde; // ~
return;
#if DMDV2
case '^':
p++;
if (*p == '^')
@@ -1128,7 +1094,6 @@ void Lexer::scan(Token *t)
else
t->value = TOKxor; // ^
return;
#endif
#define SINGLE(c,tok) case c: p++; t->value = tok; return;
@@ -1143,9 +1108,7 @@ void Lexer::scan(Token *t)
SINGLE(';', TOKsemicolon)
SINGLE(':', TOKcolon)
SINGLE('$', TOKdollar)
#if DMDV2
SINGLE('@', TOKat)
#endif
#undef SINGLE
#define DOUBLE(c1,tok1,c2,tok2) \
@@ -1161,9 +1124,6 @@ void Lexer::scan(Token *t)
DOUBLE('*', TOKmul, '=', TOKmulass)
DOUBLE('%', TOKmod, '=', TOKmodass)
#if DMDV1
DOUBLE('^', TOKxor, '=', TOKxorass)
#endif
#undef DOUBLE
case '#':
@@ -1218,9 +1178,6 @@ void Lexer::scan(Token *t)
unsigned Lexer::escapeSequence()
{ unsigned c = *p;
#ifdef TEXTUAL_ASSEMBLY_OUT
return c;
#endif
int n;
int ndigits;
@@ -1253,14 +1210,14 @@ unsigned Lexer::escapeSequence()
Lhex:
p++;
c = *p;
if (ishex(c))
if (ishex((utf8_t)c))
{ unsigned v;
n = 0;
v = 0;
while (1)
{
if (isdigit(c))
if (isdigit((utf8_t)c))
c -= '0';
else if (islower(c))
c -= 'a' - 10;
@@ -1270,7 +1227,7 @@ unsigned Lexer::escapeSequence()
c = *++p;
if (++n == ndigits)
break;
if (!ishex(c))
if (!ishex((utf8_t)c))
{ error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
break;
}
@@ -1286,7 +1243,7 @@ unsigned Lexer::escapeSequence()
break;
case '&': // named character entity
for (utf8_t *idstart = ++p; 1; p++)
for (const utf8_t *idstart = ++p; 1; p++)
{
switch (*p)
{
@@ -1316,7 +1273,7 @@ unsigned Lexer::escapeSequence()
break;
default:
if (isoctal(c))
if (isoctal((utf8_t)c))
{ unsigned v;
n = 0;
@@ -1325,7 +1282,7 @@ unsigned Lexer::escapeSequence()
{
v = v * 8 + (c - '0');
c = *++p;
} while (++n < 3 && isoctal(c));
} while (++n < 3 && isoctal((utf8_t)c));
c = v;
if (c > 0xFF)
error("0%03o is larger than a byte", c);
@@ -1484,7 +1441,6 @@ TOK Lexer::hexStringConstant(Token *t)
}
#if DMDV2
/**************************************
* Lex delimited strings:
* q"(foo(xxx))" // "foo(xxx)"
@@ -1566,15 +1522,15 @@ TOK Lexer::delimitedStringConstant(Token *t)
delimright = '>';
else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
{ // Start of identifier; must be a heredoc
Token t;
Token tok;
p--;
scan(&t); // read in heredoc identifier
if (t.value != TOKidentifier)
{ error("identifier expected for heredoc, not %s", t.toChars());
scan(&tok); // read in heredoc identifier
if (tok.value != TOKidentifier)
{ error("identifier expected for heredoc, not %s", tok.toChars());
delimright = c;
}
else
{ hereid = t.ident;
{ hereid = tok.ident;
//printf("hereid = '%s'\n", hereid->toChars());
blankrol = 1;
}
@@ -1583,10 +1539,8 @@ TOK Lexer::delimitedStringConstant(Token *t)
else
{ delimright = c;
nest = 0;
#if DMDV2
if (isspace(c))
error("delimiter cannot be whitespace");
#endif
}
}
else
@@ -1608,17 +1562,13 @@ TOK Lexer::delimitedStringConstant(Token *t)
}
else if (c == delimright)
goto Ldone;
if (startline && isalpha(c)
#if DMDV2
&& hereid
#endif
)
{ Token t;
utf8_t *psave = p;
if (startline && isalpha(c) && hereid)
{ Token tok;
const utf8_t *psave = p;
p--;
scan(&t); // read in possible heredoc identifier
//printf("endid = '%s'\n", t.ident->toChars());
if (t.value == TOKidentifier && t.ident->equals(hereid))
scan(&tok); // read in possible heredoc identifier
//printf("endid = '%s'\n", tok.ident->toChars());
if (tok.value == TOKidentifier && tok.ident->equals(hereid))
{ /* should check that rest of line is blank
*/
goto Ldone;
@@ -1633,6 +1583,8 @@ TOK Lexer::delimitedStringConstant(Token *t)
Ldone:
if (*p == '"')
p++;
else if (hereid)
error("delimited string must end in %s\"", hereid->toChars());
else
error("delimited string must end in %c\"", delimright);
t->len = stringbuffer.offset;
@@ -1663,7 +1615,7 @@ TOK Lexer::tokenStringConstant(Token *t)
{
unsigned nest = 1;
Loc start = scanloc;
utf8_t *pstart = ++p;
const utf8_t *pstart = ++p;
while (1)
{ Token tok;
@@ -1704,7 +1656,6 @@ Lerror:
return TOKstring;
}
#endif
/**************************************
@@ -1722,7 +1673,6 @@ TOK Lexer::escapeStringConstant(Token *t, int wide)
c = *p++;
switch (c)
{
#if !( TEXTUAL_ASSEMBLY_OUT )
case '\\':
switch (*p)
{
@@ -1738,7 +1688,6 @@ TOK Lexer::escapeStringConstant(Token *t, int wide)
break;
}
break;
#endif
case '\n':
scanloc.linnum++;
break;
@@ -1799,7 +1748,6 @@ TOK Lexer::charConstant(Token *t, int wide)
c = *p++;
switch (c)
{
#if ! TEXTUAL_ASSEMBLY_OUT
case '\\':
switch (*p)
{
@@ -1819,7 +1767,6 @@ TOK Lexer::charConstant(Token *t, int wide)
break;
}
break;
#endif
case '\n':
L1:
scanloc.linnum++;
@@ -1905,7 +1852,7 @@ TOK Lexer::number(Token *t)
FLAGS flags = FLAGS_decimal;
unsigned c;
utf8_t *start;
const utf8_t *start;
TOK result;
//printf("Lexer::number()\n");
@@ -1936,10 +1883,8 @@ TOK Lexer::number(Token *t)
case '.':
if (p[1] == '.') // .. is a separate token
goto done;
#if DMDV2
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
goto done;
#endif
case 'i':
case 'f':
case 'F':
@@ -1978,10 +1923,8 @@ TOK Lexer::number(Token *t)
}
if (c == '.' && p[1] != '.')
{
#if DMDV2
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
goto done;
#endif
goto real;
}
else if (c == 'i' || c == 'f' || c == 'F' ||
@@ -1999,7 +1942,7 @@ TOK Lexer::number(Token *t)
case STATE_hex0: // reading hex number
case STATE_hex:
if (!ishex(c))
if (!ishex((utf8_t)c))
{
if (c == '_') // ignore embedded _
{ p++;
@@ -2018,7 +1961,7 @@ TOK Lexer::number(Token *t)
case STATE_octal: // reading octal number
case STATE_octale: // reading octal number with non-octal digits
if (!isoctal(c))
if (!isoctal((utf8_t)c))
{
if (c == '_') // ignore embedded _
{ p++;
@@ -2078,14 +2021,10 @@ done:
n = stringbuffer.data[0] - '0';
else
{
// Convert string to integer
#if __DMC__
errno = 0;
n = strtoull((char *)stringbuffer.data,NULL,0);
if (errno == ERANGE)
error("integer overflow");
#else
// Not everybody implements strtoull()
/* Convert string to integer
* Not everybody implements strtoull()
* and besides, we don't want to deal with errno.
*/
char *p = (char *)stringbuffer.data;
int r = 10, d;
@@ -2123,7 +2062,7 @@ done:
n = n2 + d;
p++;
}
#endif
if (sizeof(n) > 8 &&
n > 0xFFFFFFFFFFFFFFFFULL) // if n needs more than 64 bits
error("integer overflow");
@@ -2154,11 +2093,9 @@ done:
break;
}
#if DMDV2
if (state == STATE_octal && n >= 8)
deprecation("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead",
n, p - psuffix, psuffix, n, p - psuffix, psuffix);
#endif
switch (flags)
{
@@ -2238,113 +2175,93 @@ done:
*/
TOK Lexer::inreal(Token *t)
#ifdef __DMC__
__in
{
assert(*p == '.' || isdigit(*p));
}
__out (result)
{
switch (result)
{
case TOKfloat32v:
case TOKfloat64v:
case TOKfloat80v:
case TOKimaginary32v:
case TOKimaginary64v:
case TOKimaginary80v:
break;
default:
assert(0);
}
}
__body
#endif /* __DMC__ */
{ int dblstate;
unsigned c;
char hex; // is this a hexadecimal-floating-constant?
TOK result;
//printf("Lexer::inreal()\n");
#ifdef DEBUG
assert(*p == '.' || isdigit(*p));
#endif
stringbuffer.reset();
dblstate = 0;
hex = 0;
Lnext:
const unsigned char *pstart = p;
char hex = 0;
unsigned c = *p++;
// Leading '0x'
if (c == '0')
{
c = *p++;
if (c == 'x' || c == 'X')
{
hex = true;
c = *p++;
}
}
// Digits to left of '.'
while (1)
{
// Get next char from input
c = *p++;
//printf("dblstate = %d, c = '%c'\n", dblstate, c);
while (1)
if (c == '.')
{
switch (dblstate)
{
case 0: // opening state
if (c == '0')
dblstate = 9;
else if (c == '.')
dblstate = 3;
else
dblstate = 1;
break;
case 9:
dblstate = 1;
if (c == 'X' || c == 'x')
{ hex++;
break;
}
case 1: // digits to left of .
case 3: // digits to right of .
case 7: // continuing exponent digits
if (!isdigit(c) && !(hex && isxdigit(c)))
{
if (c == '_')
goto Lnext; // ignore embedded '_'
dblstate++;
continue;
}
break;
case 2: // no more digits to left of .
if (c == '.')
{ dblstate++;
break;
}
case 4: // no more digits to right of .
if ((c == 'E' || c == 'e') ||
hex && (c == 'P' || c == 'p'))
{ dblstate = 5;
hex = 0; // exponent is always decimal
break;
}
if (hex)
error("binary-exponent-part required");
goto done;
case 5: // looking immediately to right of E
dblstate++;
if (c == '-' || c == '+')
break;
case 6: // 1st exponent digit expected
if (!isdigit(c))
error("exponent expected");
dblstate++;
break;
case 8: // past end of exponent digits
goto done;
}
c = *p++;
break;
}
stringbuffer.writeByte(c);
if (isdigit(c) || (hex && isxdigit(c)) || c == '_')
{
c = *p++;
continue;
}
break;
}
// Digits to right of '.'
while (1)
{
if (isdigit(c) || (hex && isxdigit(c)) || c == '_')
{
c = *p++;
continue;
}
break;
}
if (c == 'e' || c == 'E' || (hex && (c == 'p' || c == 'P')))
{
c = *p++;
if (c == '-' || c == '+')
{
c = *p++;
}
bool anyexp;
while (1)
{
if (isdigit(c) || (hex && isxdigit(c)))
{
anyexp = true;
c = *p++;
continue;
}
if (c == '_')
{
c = *p++;
continue;
}
if (!anyexp)
error("missing exponent");
break;
}
}
else if (hex)
error("exponent required for hex float");
--p;
while (pstart < p)
{
if (*pstart != '_')
stringbuffer.writeByte(*pstart);
++pstart;
}
done:
p--;
stringbuffer.writeByte(0);
TOK result;
t->float80value = Port::strtold((char *)stringbuffer.data, NULL);
errno = 0;
switch (*p)
@@ -2395,6 +2312,21 @@ done:
}
if (errno == ERANGE)
error("number is not representable");
#ifdef DEBUG
switch (result)
{
case TOKfloat32v:
case TOKfloat64v:
case TOKfloat80v:
case TOKimaginary32v:
case TOKimaginary64v:
case TOKimaginary80v:
break;
default:
assert(0);
}
#endif
return result;
}
@@ -2413,7 +2345,7 @@ void Lexer::poundLine()
scan(&tok);
if (tok.value == TOKint32v || tok.value == TOKint64v)
{ linnum = tok.uns64value - 1;
{ linnum = (int)(tok.uns64value - 1);
if (linnum != tok.uns64value - 1)
error("line number out of range");
}
@@ -2523,7 +2455,7 @@ unsigned Lexer::decodeUTF()
{
dchar_t u;
utf8_t c;
utf8_t *s = p;
const utf8_t *s = p;
size_t len;
size_t idx;
const char *msg;
@@ -2563,9 +2495,9 @@ void Lexer::getDocComment(Token *t, unsigned lineComment)
/* Start of comment text skips over / * *, / + +, or / / /
*/
utf8_t *q = t->ptr + 3; // start of comment text
const utf8_t *q = t->ptr + 3; // start of comment text
utf8_t *qend = p;
const utf8_t *qend = p;
if (ct == '*' || ct == '+')
qend -= 2;
@@ -2658,7 +2590,7 @@ void Lexer::getDocComment(Token *t, unsigned lineComment)
// It's a line comment if the start of the doc comment comes
// after other non-whitespace on the same line.
utf8_t** dc = (lineComment && anyToken)
const utf8_t** dc = (lineComment && anyToken)
? &t->lineComment
: &t->blockComment;
@@ -2674,11 +2606,11 @@ void Lexer::getDocComment(Token *t, unsigned lineComment)
* separated by a newline.
*/
utf8_t *Lexer::combineComments(utf8_t *c1, utf8_t *c2)
const utf8_t *Lexer::combineComments(const utf8_t *c1, const utf8_t *c2)
{
//printf("Lexer::combineComments('%s', '%s')\n", c1, c2);
utf8_t *c = c2;
const utf8_t *c = c2;
if (c1)
{ c = c1;
@@ -2686,14 +2618,15 @@ utf8_t *Lexer::combineComments(utf8_t *c1, utf8_t *c2)
{ size_t len1 = strlen((char *)c1);
size_t len2 = strlen((char *)c2);
c = (utf8_t *)mem.malloc(len1 + 1 + len2 + 1);
memcpy(c, c1, len1);
utf8_t *p = (utf8_t *)mem.malloc(len1 + 1 + len2 + 1);
memcpy(p, c1, len1);
if (len1 && c1[len1 - 1] != '\n')
{ c[len1] = '\n';
{ p[len1] = '\n';
len1++;
}
memcpy(c + len1, c2, len2);
c[len1 + len2] = 0;
memcpy(p + len1, c2, len2);
p[len1 + len2] = 0;
c = p;
}
}
return c;
@@ -2860,7 +2793,7 @@ static Keyword keywords[] =
{ "__parameters", TOKparameters },
{ "ref", TOKref },
{ "macro", TOKmacro },
#if DMDV2
{ "pure", TOKpure },
{ "nothrow", TOKnothrow },
{ "__gshared", TOKgshared },
@@ -2874,7 +2807,6 @@ static Keyword keywords[] =
{ "__PRETTY_FUNCTION__", TOKprettyfunc },
{ "shared", TOKshared },
{ "immutable", TOKimmutable },
#endif
};
int Token::isKeyword()
@@ -2922,9 +2854,7 @@ void Lexer::initKeywords()
Token::tochars[TOKxorass] = "^=";
Token::tochars[TOKassign] = "=";
Token::tochars[TOKconstruct] = "=";
#if DMDV2
Token::tochars[TOKblit] = "=";
#endif
Token::tochars[TOKlt] = "<";
Token::tochars[TOKgt] = ">";
Token::tochars[TOKle] = "<=";
@@ -2993,13 +2923,11 @@ void Lexer::initKeywords()
Token::tochars[TOKorass] = "|=";
Token::tochars[TOKidentifier] = "identifier";
#if DMDV2
Token::tochars[TOKat] = "@";
Token::tochars[TOKpow] = "^^";
Token::tochars[TOKpowass] = "^^=";
Token::tochars[TOKgoesto] = "=>";
Token::tochars[TOKpound] = "#";
#endif
// For debugging
Token::tochars[TOKerror] = "error";
+12 -15
View File
@@ -126,7 +126,7 @@ enum TOK
TOKfloat32, TOKfloat64, TOKfloat80,
TOKimaginary32, TOKimaginary64, TOKimaginary80,
TOKcomplex32, TOKcomplex64, TOKcomplex80,
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
TOKchar, TOKwchar, TOKdchar, TOKbool,
// 152
// Aggregates
@@ -157,7 +157,7 @@ enum TOK
TOKargTypes,
TOKref,
TOKmacro,
#if DMDV2
TOKparameters,
TOKtraits,
TOKoverloadset,
@@ -176,7 +176,6 @@ enum TOK
TOKgoesto,
TOKvector,
TOKpound,
#endif
// LDC specific
#if IN_LLVM
@@ -190,7 +189,7 @@ enum TOK
#define BASIC_TYPES \
TOKwchar: case TOKdchar: \
case TOKbit: case TOKbool: case TOKchar: \
case TOKbool: case TOKchar: \
case TOKint8: case TOKuns8: \
case TOKint16: case TOKuns16: \
case TOKint32: case TOKuns32: \
@@ -232,10 +231,10 @@ struct Token
{
Token *next;
Loc loc;
utf8_t *ptr; // pointer to first character of this token within buffer
const utf8_t *ptr; // pointer to first character of this token within buffer
TOK value;
utf8_t *blockComment; // doc comment string prior to this token
utf8_t *lineComment; // doc comment for previous token
const utf8_t *blockComment; // doc comment string prior to this token
const utf8_t *lineComment; // doc comment for previous token
union
{
// Integers
@@ -277,9 +276,9 @@ public:
Loc scanloc; // for error messages
utf8_t *base; // pointer to start of buffer
utf8_t *end; // past end of buffer
utf8_t *p; // current character
const utf8_t *base; // pointer to start of buffer
const utf8_t *end; // past end of buffer
const utf8_t *p; // current character
Token token;
Module *mod;
int doDocComment; // collect doc comment information
@@ -287,7 +286,7 @@ public:
int commentToken; // !=0 means comments are TOKcomment's
Lexer(Module *mod,
utf8_t *base, size_t begoffset, size_t endoffset,
const utf8_t *base, size_t begoffset, size_t endoffset,
int doDocComment, int commentToken);
static void initKeywords();
@@ -304,10 +303,8 @@ public:
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);
@@ -320,8 +317,8 @@ public:
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
static int isValidIdentifier(char *p);
static utf8_t *combineComments(utf8_t *c1, utf8_t *c2);
static int isValidIdentifier(const char *p);
static const utf8_t *combineComments(const utf8_t *c1, const utf8_t *c2);
};
#endif /* DMD_LEXER_H */
+1 -1
View File
@@ -20,7 +20,7 @@ class Library
public:
static Library *factory();
virtual void setFilename(char *dir, char *filename) = 0;
virtual void setFilename(const char *dir, const char *filename) = 0;
virtual void addObject(const char *module_name, void *buf, size_t buflen) = 0;
virtual void addLibrary(void *buf, size_t buflen) = 0;
virtual void write() = 0;
+15 -15
View File
@@ -21,16 +21,16 @@
#include "macro.h"
int isIdStart(utf8_t *p);
int isIdTail(utf8_t *p);
int utfStride(utf8_t *p);
int isIdStart(const utf8_t *p);
int isIdTail(const utf8_t *p);
int utfStride(const utf8_t *p);
utf8_t *memdup(utf8_t *p, size_t len)
utf8_t *memdup(const utf8_t *p, size_t len)
{
return (utf8_t *)memcpy(mem.malloc(len), p, len);
}
Macro::Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen)
Macro::Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen)
{
next = NULL;
@@ -51,7 +51,7 @@ Macro::Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen)
}
Macro *Macro::search(utf8_t *name, size_t namelen)
Macro *Macro::search(const utf8_t *name, size_t namelen)
{ Macro *table;
//printf("Macro::search(%.*s)\n", namelen, name);
@@ -67,7 +67,7 @@ Macro *Macro::search(utf8_t *name, size_t namelen)
return table;
}
Macro *Macro::define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text, size_t textlen)
Macro *Macro::define(Macro **ptable, const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen)
{
//printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text);
@@ -98,7 +98,7 @@ Macro *Macro::define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text,
* -1: get 2nd through end
*/
size_t extractArgN(utf8_t *p, size_t end, utf8_t **pmarg, size_t *pmarglen, int n)
size_t extractArgN(const utf8_t *p, size_t end, const utf8_t **pmarg, size_t *pmarglen, int n)
{
/* Scan forward for matching right parenthesis.
* Nest parentheses.
@@ -238,7 +238,7 @@ size_t extractArgN(utf8_t *p, size_t end, utf8_t **pmarg, size_t *pmarglen, int
*/
void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
utf8_t *arg, size_t arglen)
const utf8_t *arg, size_t arglen)
{
#if 0
printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg);
@@ -259,7 +259,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
arg = memdup(arg, arglen);
for (size_t u = start; u + 1 < end; )
{
utf8_t *p = buf->data; // buf->data is not loop invariant
utf8_t *p = (utf8_t *)buf->data; // buf->data is not loop invariant
/* Look for $0, but not $$0, and replace it with arg.
*/
@@ -276,7 +276,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
utf8_t c = p[u + 1];
int n = (c == '+') ? -1 : c - '0';
utf8_t *marg;
const utf8_t *marg;
size_t marglen;
extractArgN(arg, arglen, &marg, &marglen, n);
if (marglen == 0)
@@ -327,7 +327,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
*/
for (size_t u = start; u + 4 < end; )
{
utf8_t *p = buf->data; // buf->data is not loop invariant
utf8_t *p = (utf8_t *)buf->data; // buf->data is not loop invariant
/* A valid start of macro expansion is $(c, where c is
* an id start character, and not $$(c.
@@ -338,7 +338,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
utf8_t *name = p + u + 2;
size_t namelen = 0;
utf8_t *marg;
const utf8_t *marg;
size_t marglen;
size_t v;
@@ -427,7 +427,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
end -= v + 1 - u;
u += mend - (v + 1);
#endif
mem.free(marg);
mem.free((utf8_t *)marg);
//printf("u = %d, end = %d\n", u, end);
//printf("#%.*s#\n", end - u, &buf->data[u]);
continue;
@@ -444,7 +444,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
}
u++;
}
mem.free(arg);
mem.free((utf8_t *)arg);
*pend = end;
nest--;
}
+6 -6
View File
@@ -24,22 +24,22 @@ struct Macro
private:
Macro *next; // next in list
utf8_t *name; // macro name
const utf8_t *name; // macro name
size_t namelen; // length of macro name
utf8_t *text; // macro replacement text
const utf8_t *text; // macro replacement text
size_t textlen; // length of replacement text
int inuse; // macro is in use (don't expand)
Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen);
Macro *search(utf8_t *name, size_t namelen);
Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen);
Macro *search(const utf8_t *name, size_t namelen);
public:
static Macro *define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text, size_t textlen);
static Macro *define(Macro **ptable, const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen);
void expand(OutBuffer *buf, size_t start, size_t *pend,
utf8_t *arg, size_t arglen);
const utf8_t *arg, size_t arglen);
};
#endif
+38 -44
View File
@@ -67,7 +67,12 @@ char *mangle(Declaration *sthis, bool isv)
}
else
buf.prependstring("0");
s = s->parent;
TemplateInstance *ti = s->isTemplateInstance();
if (ti && !ti->isTemplateMixin())
s = ti->tempdecl->parent;
else
s = s->parent;
} while (s);
// buf.prependstring("_D");
@@ -118,23 +123,9 @@ L1:
}
const char *Declaration::mangle(bool isv)
#if __DMC__
__out(result)
{
int len = strlen(result);
{
char *p;
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() || linkage == LINKcpp) // if at global scope
{
@@ -150,34 +141,52 @@ const char *Declaration::mangle(bool isv)
case LINKc:
case LINKwindows:
case LINKpascal:
return ident->toChars();
p = ident->toChars();
goto Lret;
case LINKcpp:
#if CPP_MANGLE
return cpp_mangle(this);
p = cpp_mangle(this);
#else
// Windows C++ mangling is done by C++ back end
return ident->toChars();
p = ident->toChars();
#endif
goto Lret;
case LINKdefault:
error("forward declaration");
return ident->toChars();
p = ident->toChars();
goto Lret;
default:
fprintf(stderr, "'%s', linkage = %d\n", toChars(), linkage);
assert(0);
}
}
char *p = ::mangle(this, isv);
{
p = ::mangle(this, isv);
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);
Lret:
#ifdef DEBUG
size_t len = strlen(p);
assert(len > 0);
//printf("mangle: '%s' => '%s'\n", toChars(), p);
for (size_t i = 0; i < len; i++)
{
assert(p[i] == '_' ||
p[i] == '@' ||
isalnum(p[i]) || p[i] & 0x80);
}
#endif
return p;
}
}
/******************************************************************************
* Normally FuncDeclaration and FuncAliasDeclaration have overloads.
@@ -222,14 +231,7 @@ const char *FuncAliasDeclaration::mangle(bool isv)
* Returns exact mangled name of function.
*/
const char *FuncDeclaration::mangleExact(bool isv)
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
{
assert(!isFuncAliasDeclaration());
if (mangleOverride)
@@ -243,22 +245,15 @@ const char *FuncDeclaration::mangleExact(bool isv)
assert(this);
return Declaration::mangle(isv);
}
}
const char *VarDeclaration::mangle(bool isv)
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
{
if (mangleOverride)
return mangleOverride;
return Declaration::mangle();
}
}
const char *TypedefDeclaration::mangle(bool isv)
{
@@ -269,7 +264,6 @@ const char *TypedefDeclaration::mangle(bool isv)
const char *AggregateDeclaration::mangle(bool isv)
{
#if 1
//printf("AggregateDeclaration::mangle() '%s'\n", toChars());
if (Dsymbol *p = toParent2())
{ if (FuncDeclaration *fd = p->isFuncDeclaration())
@@ -279,7 +273,7 @@ const char *AggregateDeclaration::mangle(bool isv)
return id;
}
}
#endif
return Dsymbol::mangle(isv);
}
@@ -341,7 +335,7 @@ const char *TemplateInstance::mangle(bool isv)
error("is not defined");
else
{
Dsymbol *par = enclosing || isTemplateMixin() ? parent : tempdecl->parent;
Dsymbol *par = isTemplateMixin() ? parent : tempdecl->parent;
if (par)
{
const char *p = par->mangle(isv);
+55 -109
View File
@@ -47,9 +47,9 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
#endif
#if !IN_LLVM
int response_expand(size_t *pargc, char ***pargv);
int response_expand(size_t *pargc, const char ***pargv);
void browse(const char *url);
void getenv_setargv(const char *envvar, size_t *pargc, char** *pargv);
void getenv_setargv(const char *envvar, size_t *pargc, const char** *pargv);
void obj_start(char *srcfile);
void obj_end(Library *library, File *objfile);
@@ -57,7 +57,7 @@ void obj_end(Library *library, File *objfile);
void printCtfePerformanceStats();
static bool parse_arch(size_t argc, char** argv, bool is64bit);
static bool parse_arch(size_t argc, const char** argv, bool is64bit);
/** Normalize path by turning forward slashes into backslashes */
void toWinPath(char *src)
@@ -384,7 +384,7 @@ Usage:\n\
-debuglib=name set symbolic debug library to name\n\
-defaultlib=name set default library to name\n\
-deps print module dependencies (imports/file/version/debug/lib)\n\
-deps=filename write module dependencies to filename (only imports - deprecated)\n%s\
-deps=filename write module dependencies to filename (only imports)\n%s\
-g add symbolic debug info\n\
-gc add symbolic debug info, pretend to be C\n\
-gs always emit stack frame\n\
@@ -432,14 +432,6 @@ Usage:\n\
extern signed char tyalignsize[];
#if _WIN32 && __DMC__
extern "C"
{
extern int _xi_a;
extern int _end;
}
#endif
static Module *entrypoint = NULL;
/************************************
@@ -457,7 +449,7 @@ void genCmain(Scope *sc)
/* The D code to be generated is provided as D source code in the form of a string.
* Note that Solaris, for unknown reasons, requires both a main() and an _main()
*/
static utf8_t code[] = "extern(C) {\n\
static const utf8_t cmaincode[] = "extern(C) {\n\
int _d_run_main(int argc, char **argv, void* mainFunc);\n\
int _Dmain(char[][] args);\n\
int main(int argc, char **argv) { return _d_run_main(argc, argv, &_Dmain); }\n\
@@ -468,7 +460,7 @@ void genCmain(Scope *sc)
Identifier *id = Id::entrypoint;
Module *m = new Module("__entrypoint.d", id, 0, 0);
Parser p(m, code, sizeof(code) / sizeof(code[0]), 0);
Parser p(m, cmaincode, strlen((const char *)cmaincode), 0);
p.scanloc = Loc();
p.nextToken();
m->members = p.parseModule();
@@ -486,18 +478,10 @@ void genCmain(Scope *sc)
entrypoint = m;
}
int tryMain(size_t argc, char *argv[])
int tryMain(size_t argc, const char *argv[])
{
mem.init(); // initialize storage allocator
mem.setStackBottom(&argv);
#if _WIN32 && __DMC__
mem.addroots((char *)&_xi_a, (char *)&_end);
#endif
Strings files;
Strings libmodules;
char *p;
Module *m;
size_t argcstart = argc;
int setdebuglib = 0;
char noboundscheck = 0;
@@ -552,7 +536,7 @@ int tryMain(size_t argc, char *argv[])
global.params.is64bit = (sizeof(size_t) == 8);
#if TARGET_WINDOS
global.params.is64bit = 0;
global.params.is64bit = false;
global.params.defaultlibname = "phobos";
#elif TARGET_LINUX
global.params.defaultlibname = "libphobos2.a";
@@ -597,9 +581,7 @@ int tryMain(size_t argc, char *argv[])
VersionCondition::addPredefinedGlobalIdent("LittleEndian");
//VersionCondition::addPredefinedGlobalIdent("D_Bits");
#if DMDV2
VersionCondition::addPredefinedGlobalIdent("D_Version2");
#endif
VersionCondition::addPredefinedGlobalIdent("all");
#if _WIN32
@@ -611,7 +593,7 @@ int tryMain(size_t argc, char *argv[])
#endif
size_t dflags_argc = 0;
char** dflags_argv = NULL;
const char** dflags_argv = NULL;
getenv_setargv("DFLAGS", &dflags_argc, &dflags_argv);
bool is64bit = global.params.is64bit; // use default
@@ -619,7 +601,8 @@ int tryMain(size_t argc, char *argv[])
is64bit = parse_arch(dflags_argc, dflags_argv, is64bit);
global.params.is64bit = is64bit;
inifile(argv[0], inifilename, is64bit ? "Environment64" : "Environment32");
const char *envsec = is64bit ? "Environment64" : "Environment32";
inifile(argv[0], inifilename, envsec);
getenv_setargv("DFLAGS", &argc, &argv);
@@ -632,7 +615,7 @@ int tryMain(size_t argc, char *argv[])
for (size_t i = 1; i < argc; i++)
{
p = argv[i];
const char *p = argv[i];
if (*p == '-')
{
if (strcmp(p + 1, "allinst") == 0)
@@ -657,10 +640,10 @@ int tryMain(size_t argc, char *argv[])
{ long percent;
errno = 0;
percent = strtol(p + 5, &p, 10);
percent = strtol(p + 5, (char **)&p, 10);
if (*p || errno || percent > 100)
goto Lerror;
global.params.covPercent = percent;
global.params.covPercent = (unsigned char)percent;
}
else
goto Lerror;
@@ -704,14 +687,13 @@ int tryMain(size_t argc, char *argv[])
global.params.trace = 1;
}
else if (strcmp(p + 1, "m32") == 0)
global.params.is64bit = 0;
global.params.is64bit = false;
else if (strcmp(p + 1, "m64") == 0)
global.params.is64bit = 1;
global.params.is64bit = true;
else if (strcmp(p + 1, "profile") == 0)
global.params.trace = 1;
else if (strcmp(p + 1, "v") == 0)
global.params.verbose = 1;
#if DMDV2
else if (strcmp(p + 1, "vtls") == 0)
global.params.vtls = 1;
else if (memcmp(p + 1, "transition", 10) == 0)
@@ -740,7 +722,7 @@ Language changes listed by -transition=id:\n\
{ long num;
errno = 0;
num = strtol(p + 12, &p, 10);
num = strtol(p + 12, (char **)&p, 10);
if (*p || errno || num > INT_MAX)
goto Lerror;
switch (num) // Bugzilla issue number
@@ -767,7 +749,6 @@ Language changes listed by -transition=id:\n\
else
goto Lerror;
}
#endif
else if (strcmp(p + 1, "w") == 0)
global.params.warnings = 1;
else if (strcmp(p + 1, "wi") == 0)
@@ -786,7 +767,7 @@ Language changes listed by -transition=id:\n\
if (!p[3])
goto Lnoarg;
#if _WIN32
toWinPath(p + 3);
toWinPath((char *)p + 3);
#endif
global.params.objdir = p + 3;
break;
@@ -795,7 +776,7 @@ Language changes listed by -transition=id:\n\
if (!p[3])
goto Lnoarg;
#if _WIN32
toWinPath(p + 3);
toWinPath((char *)p + 3);
#endif
global.params.objname = p + 3;
break;
@@ -892,10 +873,8 @@ Language changes listed by -transition=id:\n\
global.params.release = 1;
else if (strcmp(p + 1, "betterC") == 0)
global.params.betterC = 1;
#if DMDV2
else if (strcmp(p + 1, "noboundscheck") == 0)
noboundscheck = 1;
#endif
else if (strcmp(p + 1, "unittest") == 0)
global.params.useUnitTests = 1;
else if (p[1] == 'I')
@@ -922,7 +901,7 @@ Language changes listed by -transition=id:\n\
{ long level;
errno = 0;
level = strtol(p + 7, &p, 10);
level = strtol(p + 7, (char **)&p, 10);
if (*p || errno || level > INT_MAX)
goto Lerror;
DebugCondition::setGlobalLevel((int)level);
@@ -948,7 +927,7 @@ Language changes listed by -transition=id:\n\
{ long level;
errno = 0;
level = strtol(p + 9, &p, 10);
level = strtol(p + 9, (char **)&p, 10);
if (*p || errno || level > INT_MAX)
goto Lerror;
VersionCondition::setGlobalLevel((int)level);
@@ -1017,39 +996,19 @@ Language changes listed by -transition=id:\n\
else if (memcmp(p + 1, "man", 3) == 0)
{
#if _WIN32
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
#else
browse("http://dlang.org/dmd-windows.html");
#endif
#endif
#if linux
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
#else
browse("http://dlang.org/dmd-linux.html");
#endif
#endif
#if __APPLE__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-osx.html");
#else
browse("http://dlang.org/dmd-osx.html");
#endif
#endif
#if __FreeBSD__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html");
#else
browse("http://dlang.org/dmd-freebsd.html");
#endif
#endif
#if __OpenBSD__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-openbsd.html");
#else
browse("http://dlang.org/dmd-openbsd.html");
#endif
#endif
exit(EXIT_SUCCESS);
}
@@ -1103,7 +1062,7 @@ Language changes listed by -transition=id:\n\
if(global.params.is64bit != is64bit)
error(Loc(), "the architecture must not be changed in the %s section of %s",
is64bit ? "Environment64" : "Environment32", inifilename);
envsec, inifilename);
// Target uses 64bit pointers.
global.params.isLP64 = global.params.is64bit;
@@ -1175,15 +1134,7 @@ Language changes listed by -transition=id:\n\
global.params.objname = NULL;
// Haven't investigated handling these options with multiobj
if (!global.params.cov && !global.params.trace
#if 0 && TARGET_WINDOS
/* multiobj causes class/struct debug info to be attached to init-data,
* but this will not be linked into the executable, so this info is lost.
* Bugzilla 4014
*/
&& !global.params.symdebug
#endif
)
if (!global.params.cov && !global.params.trace)
global.params.multiobj = 1;
}
else if (global.params.run)
@@ -1234,14 +1185,12 @@ Language changes listed by -transition=id:\n\
VersionCondition::addPredefinedGlobalIdent("D_Coverage");
if (global.params.pic)
VersionCondition::addPredefinedGlobalIdent("D_PIC");
#if DMDV2
if (global.params.useUnitTests)
VersionCondition::addPredefinedGlobalIdent("unittest");
if (global.params.useAssert)
VersionCondition::addPredefinedGlobalIdent("assert");
if (noboundscheck)
VersionCondition::addPredefinedGlobalIdent("D_NoBoundsChecks");
#endif
VersionCondition::addPredefinedGlobalIdent("D_HardFloat");
@@ -1266,7 +1215,7 @@ Language changes listed by -transition=id:\n\
{
for (size_t i = 0; i < global.params.imppath->dim; i++)
{
char *path = (*global.params.imppath)[i];
const char *path = (*global.params.imppath)[i];
Strings *a = FileName::splitPath(path);
if (a)
@@ -1283,7 +1232,7 @@ Language changes listed by -transition=id:\n\
{
for (size_t i = 0; i < global.params.fileImppath->dim; i++)
{
char *path = (*global.params.fileImppath)[i];
const char *path = (*global.params.fileImppath)[i];
Strings *a = FileName::splitPath(path);
if (a)
@@ -1306,22 +1255,18 @@ Language changes listed by -transition=id:\n\
bool firstmodule = true;
for (size_t i = 0; i < files.dim; i++)
{
const char *ext;
char *name;
;
const char *name;
p = files[i];
const char *p = files[i];
#if _WIN32
// Convert / to \ so linker will work
for (size_t j = 0; p[j]; j++)
{
if (p[j] == '/')
p[j] = '\\';
}
toWinPath((char *)p);
#endif
p = (char *)FileName::name(p); // strip path
ext = FileName::ext(p);
p = FileName::name(p); // strip path
const char *ext = FileName::ext(p);
char *newname;
if (ext)
{ /* Deduce what to do with a file based on its extension
*/
@@ -1386,9 +1331,10 @@ Language changes listed by -transition=id:\n\
{
ext--; // skip onto '.'
assert(*ext == '.');
name = (char *)mem.malloc((ext - p) + 1);
memcpy(name, p, ext - p);
name[ext - p] = 0; // strip extension
newname = (char *)mem.malloc((ext - p) + 1);
memcpy(newname, p, ext - p);
newname[ext - p] = 0; // strip extension
name = newname;
if (name[0] == 0 ||
strcmp(name, "..") == 0 ||
@@ -1415,11 +1361,11 @@ Language changes listed by -transition=id:\n\
*/
Identifier *id = Lexer::idPool(name);
m = new Module(files[i], id, global.params.doDocComments, global.params.doHdrGeneration);
Module *m = new Module(files[i], id, global.params.doDocComments, global.params.doHdrGeneration);
modules.push(m);
if (firstmodule)
{ global.params.objfiles->push((char *)m->objfile->name->str);
{ global.params.objfiles->push(m->objfile->name->str);
firstmodule = false;
}
}
@@ -1450,7 +1396,7 @@ Language changes listed by -transition=id:\n\
AsyncRead *aw = AsyncRead::create(modules.dim);
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
aw->addFile(m->srcfile);
}
aw->start();
@@ -1458,7 +1404,7 @@ Language changes listed by -transition=id:\n\
// Single threaded
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
m->read(Loc());
}
#endif
@@ -1468,7 +1414,7 @@ Language changes listed by -transition=id:\n\
size_t filecount = modules.dim;
for (size_t filei = 0, modi = 0; filei < filecount; filei++, modi++)
{
m = modules[modi];
Module *m = modules[modi];
if (global.params.verbose)
fprintf(global.stdmsg, "parse %s\n", m->toChars());
if (!Module::rootModule)
@@ -1528,7 +1474,7 @@ Language changes listed by -transition=id:\n\
*/
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "import %s\n", m->toChars());
m->genhdrfile();
@@ -1540,7 +1486,7 @@ Language changes listed by -transition=id:\n\
// load all unconditional imports for better symbol resolving
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "importall %s\n", m->toChars());
m->importAll(NULL);
@@ -1553,7 +1499,7 @@ Language changes listed by -transition=id:\n\
// Do semantic analysis
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "semantic %s\n", m->toChars());
m->semantic();
@@ -1567,7 +1513,7 @@ Language changes listed by -transition=id:\n\
// Do pass 2 semantic analysis
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "semantic2 %s\n", m->toChars());
m->semantic2();
@@ -1578,7 +1524,7 @@ Language changes listed by -transition=id:\n\
// Do pass 3 semantic analysis
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
m->semantic3();
@@ -1599,7 +1545,7 @@ Language changes listed by -transition=id:\n\
// since otherwise functions in them cannot be inlined
for (size_t i = 0; i < Module::amodules.dim; i++)
{
m = Module::amodules[i];
Module *m = Module::amodules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
m->semantic3();
@@ -1630,7 +1576,7 @@ Language changes listed by -transition=id:\n\
{
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "inline scan %s\n", m->toChars());
m->inlineScan();
@@ -1652,7 +1598,7 @@ Language changes listed by -transition=id:\n\
// Add input object and input library files to output library
for (size_t i = 0; i < libmodules.dim; i++)
{
char *p = libmodules[i];
const char *p = libmodules[i];
library->addObject(p, NULL, 0);
}
}
@@ -1711,7 +1657,7 @@ Language changes listed by -transition=id:\n\
obj_start(modules[0]->srcfile->toChars());
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "code %s\n", m->toChars());
m->genobjfile(0);
@@ -1729,7 +1675,7 @@ Language changes listed by -transition=id:\n\
{
for (size_t i = 0; i < modules.dim; i++)
{
m = modules[i];
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "code %s\n", m->toChars());
if (global.params.obj)
@@ -1794,7 +1740,7 @@ Language changes listed by -transition=id:\n\
return status;
}
int main(int argc, char *argv[])
int main(int argc, const char *argv[])
{
int status = -1;
#if WINDOWS_SEH
@@ -1821,7 +1767,7 @@ int main(int argc, char *argv[])
* The string is separated into arguments, processing \ and ".
*/
void getenv_setargv(const char *envvar, size_t *pargc, char** *pargv)
void getenv_setargv(const char *envvar, size_t *pargc, const char** *pargv)
{
char *p;
@@ -1965,10 +1911,10 @@ void escapePath(OutBuffer *buf, const char *fname)
* to detect the desired architecture.
*/
static bool parse_arch(size_t argc, char** argv, bool is64bit)
static bool parse_arch(size_t argc, const char** argv, bool is64bit)
{
for (size_t i = 0; i < argc; ++i)
{ char* p = argv[i];
{ const char* p = argv[i];
if (p[0] == '-')
{
if (strcmp(p + 1, "m32") == 0)
+46 -45
View File
@@ -96,12 +96,12 @@ void unittests();
#define DMDV1 0
#define DMDV2 1 // Version 2.0 features
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
#define SNAN_DEFAULT_INIT 1 // if floats are default initialized to signalling NaN
#define MODULEINFO_IS_STRUCT 1 // if ModuleInfo is a struct rather than a class
#define PULL93 0 // controversial pull #93 for bugzilla 3449
// Set if C++ mangling is done by the front end
#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || IN_LLVM))
#define CPP_MANGLE (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS)
/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD, TARGET_OPENBSD and
* TARGET_SOLARIS, which are
@@ -135,7 +135,7 @@ struct OutBuffer;
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct Array;
typedef Array<class Identifier> Identifiers;
typedef Array<char> Strings;
typedef Array<const char> Strings;
#if IN_LLVM
enum OUTPUTFLAG
@@ -151,9 +151,9 @@ typedef unsigned char ubyte;
// Put command line switches in here
struct Param
{
#if IN_LLVM
bool obj; // write object file
bool link; // perform link
#if IN_LLVM
bool verbose; // verbose compile
bool vtls; // identify thread local variables
bool vfield; // identify non-mutable field variables
@@ -168,6 +168,8 @@ struct Param
bool isOpenBSD; // generate code for OpenBSD
bool isSolaris; // generate code for Solaris
#else
char obj; // write object file
char link; // perform link
char dll; // generate shared dynamic library
char lib; // write library file instead of object file(s)
char multiobj; // break one object file into multiple ones
@@ -181,7 +183,7 @@ struct Param
bool alwaysframe; // always emit standard stack frame
bool optimize; // run optimizer
char map; // generate linker .map file
char is64bit; // generate 64 bit code
bool is64bit; // generate 64 bit code
char isLP64; // generate code for LP64
char isLinux; // generate code for linux
char isOSX; // generate code for Mac OSX
@@ -217,8 +219,6 @@ struct Param
ubyte Dversion; // D version number
bool ignoreUnsupportedPragmas; // rather than error on them
bool enforcePropertySyntax;
bool addMain; // LDC_FIXME: Implement.
bool allInst; // LDC_FIXME: Implement.
#else
bool pic; // generate position-independent-code for shared libs
bool cov; // generate code coverage data
@@ -227,38 +227,51 @@ struct Param
char ignoreUnsupportedPragmas; // rather than error on them
char enforcePropertySyntax;
char betterC; // be a "better C" compiler; no dependency on D runtime
#endif
bool addMain; // add a default main() function
bool allInst; // generate code for all template instantiations
#endif
char *argv0; // program name
const char *argv0; // program name
Strings *imppath; // array of char*'s of where to look for import modules
Strings *fileImppath; // array of char*'s of where to look for file import modules
char *objdir; // .obj/.lib file output directory
char *objname; // .obj file output name
const char *objdir; // .obj/.lib file output directory
const char *objname; // .obj file output name
const char *libname; // .lib file output name
bool doDocComments; // process embedded documentation comments
char *docdir; // write documentation file to docdir directory
char *docname; // write documentation file to docname
Strings *ddocfiles; // macro include files for Ddoc
#if IN_LLVM
bool doDocComments; // process embedded documentation comments
#else
char doDocComments; // process embedded documentation comments
#endif
const char *docdir; // write documentation file to docdir directory
const char *docname; // write documentation file to docname
Strings *ddocfiles; // macro include files for Ddoc
bool doHdrGeneration; // process embedded documentation comments
char *hdrdir; // write 'header' file to docdir directory
char *hdrname; // write 'header' file to docname
#if IN_LLVM
bool doHdrGeneration; // process embedded documentation comments
#else
char doHdrGeneration; // process embedded documentation comments
#endif
const char *hdrdir; // write 'header' file to docdir directory
const char *hdrname; // write 'header' file to docname
bool doXGeneration; // write JSON file
char *xfilename; // write JSON file to xfilename
#if IN_LLVM
bool doXGeneration; // write JSON file
#else
char doXGeneration; // write JSON file
#endif
const char *xfilename; // write JSON file to xfilename
unsigned debuglevel; // debug level
unsigned debuglevel; // debug level
Strings *debugids; // debug identifiers
unsigned versionlevel; // version level
unsigned versionlevel; // version level
Strings *versionids; // version identifiers
Strings *defaultlibnames; // default libraries for non-debug builds
Strings *debuglibnames; // default libraries for debug builds
char *moduleDepsFile; // filename for deps output
const char *moduleDepsFile; // filename for deps output
OutBuffer *moduleDeps; // contents to be written to deps file
#if IN_DMD
@@ -276,17 +289,17 @@ struct Param
bool run; // run resulting executable
#if !IN_LLVM
size_t runargs_length;
char** runargs; // arguments for executable
const char** runargs; // arguments for executable
#endif
// Linker stuff
Strings *objfiles;
Strings *linkswitches;
Strings *libfiles;
char *deffile;
char *resfile;
char *exefile;
char *mapfile;
const char *deffile;
const char *resfile;
const char *exefile;
const char *mapfile;
#if IN_LLVM
// Whether to keep all function bodies in .di file generation or to strip
// those of plain functions. For DMD, this is govenered by the -inline
@@ -399,12 +412,7 @@ extern Global global;
#include "longdouble.h"
#ifdef __DMC__
#include <complex.h>
typedef _Complex long double complex_t;
#else
#include "complex_t.h"
#endif
#include "complex_t.h"
// Be careful not to care about sign when using dinteger_t
//typedef uint64_t integer_t;
@@ -455,13 +463,6 @@ struct Loc
bool equals(const Loc& loc);
};
#ifndef GCC_SAFE_DMD
#undef TRUE
#define TRUE 1
#undef FALSE
#define FALSE 0
#endif
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
// in interface vtbl[]'s
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
@@ -497,9 +498,7 @@ enum MATCH
{
MATCHnomatch, // no match
MATCHconvert, // match with conversions
#if DMDV2
MATCHconst, // match with conversion to const
#endif
MATCHexact // exact match
};
@@ -520,6 +519,8 @@ void vdeprecation(Loc loc, const char *format, va_list ap, const char *p1 = NULL
#if defined(__GNUC__) || defined(__clang__)
__attribute__((noreturn))
#elif _MSC_VER
__declspec(noreturn)
#endif
void fatal();
@@ -538,7 +539,7 @@ void halt();
#if !IN_LLVM
class Dsymbol;
class Library;
class File;
struct File;
void obj_start(char *srcfile);
void obj_end(Library *library, File *objfile);
void obj_append(Dsymbol *s);
+56 -33
View File
@@ -44,7 +44,7 @@ void Module::init()
modules = new DsymbolTable();
}
Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
Module::Module(const char *filename, Identifier *ident, int doDocComment, int doHdrGen)
: Package(ident)
{
const char *srcfilename;
@@ -90,7 +90,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
macrotable = NULL;
escapetable = NULL;
safe = FALSE;
safe = false;
#if IN_DMD
doppelganger = 0;
cov = NULL;
@@ -101,7 +101,30 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
namelen = 0;
srcfilename = FileName::defaultExt(filename, global.mars_ext);
if (!FileName::equalsExt(srcfilename, global.mars_ext) &&
#if IN_LLVM
bool allow_no_extension = global.params.isLinux || global.params.isOSX ||
global.params.isFreeBSD || global.params.isOpenBSD ||
global.params.isSolaris;
#else
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
/* Allow 'script' D source files to have no extension.
*/
bool allow_no_extension = true;
#else
bool allow_no_extension = false;
#endif
#endif
if (allow_no_extension &&
global.params.run &&
!FileName::ext(filename) &&
FileName::exists(srcfilename) == 0 &&
FileName::exists(filename) == 1)
{
FileName::free(srcfilename);
srcfilename = FileName::removeExt(filename); // just does a mem.strdup(filename)
}
else if (!FileName::equalsExt(srcfilename, global.mars_ext) &&
!FileName::equalsExt(srcfilename, global.hdr_ext) &&
!FileName::equalsExt(srcfilename, "dd"))
{
@@ -303,7 +326,7 @@ bool Module::read(Loc loc)
{
for (size_t i = 0; i < global.path->dim; i++)
{
char *p = (*global.path)[i];
const char *p = (*global.path)[i];
fprintf(stderr, "import path[%llu] = %s\n", (ulonglong)i, p);
}
}
@@ -399,7 +422,7 @@ void Module::parse()
char *srcname = srcfile->name->toChars();
//printf("Module::parse(srcname = '%s')\n", srcname);
utf8_t *buf = srcfile->buffer;
utf8_t *buf = (utf8_t *)srcfile->buffer;
size_t buflen = srcfile->len;
if (buflen >= 2)
@@ -578,28 +601,30 @@ void Module::parse()
#endif
return;
}
{
#if IN_LLVM
Parser p(this, buf, buflen, gen_docs);
Parser p(this, buf, buflen, gen_docs);
#else
Parser p(this, buf, buflen, docfile != NULL);
Parser p(this, buf, buflen, docfile != NULL);
#endif
p.nextToken();
members = p.parseModule();
p.nextToken();
members = p.parseModule();
md = p.md;
numlines = p.scanloc.linnum;
}
if (srcfile->ref == 0)
::free(srcfile->buffer);
srcfile->buffer = NULL;
srcfile->len = 0;
md = p.md;
numlines = p.scanloc.linnum;
/* The symbol table into which the module is to be inserted.
*/
DsymbolTable *dst;
if (md)
{ /* A ModuleDeclaration, md, was provided.
{
/* A ModuleDeclaration, md, was provided.
* The ModuleDeclaration sets the packages this module appears in, and
* the name of this module.
*/
@@ -608,17 +633,17 @@ void Module::parse()
Package *ppack = NULL;
dst = Package::resolve(md->packages, &this->parent, &ppack);
assert(dst);
#if 0
if (ppack && ppack->isModule())
Module *m = ppack ? ppack->isModule() : NULL;
if (m && strcmp(m->srcfile->name->name(), "package.d") != 0)
{
error(loc, "package name '%s' in file %s conflicts with usage as a module name in file %s",
ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars());
dst = modules;
::error(md->loc, "package name '%s' conflicts with usage as a module name in file %s",
ppack->toPrettyChars(), m->srcfile->toChars());
}
#endif
}
else
{ /* The name of the module is set to the source file name.
{
/* The name of the module is set to the source file name.
* There are no packages.
*/
dst = modules; // and so this module goes into global module symbol table
@@ -665,8 +690,7 @@ void Module::parse()
*/
Dsymbol *prev = dst->lookup(ident);
assert(prev);
Module *mprev = prev->isModule();
if (mprev)
if (Module *mprev = prev->isModule())
{
if (strcmp(srcname, mprev->srcfile->toChars()) == 0)
error(loc, "from file %s must be imported as module '%s'",
@@ -675,10 +699,8 @@ void Module::parse()
error(loc, "from file %s conflicts with another module %s from file %s",
srcname, mprev->toChars(), mprev->srcfile->toChars());
}
else
else if (Package *pkg = prev->isPackage())
{
Package *pkg = prev->isPackage();
assert(pkg);
if (pkg->isPkgMod == PKGunknown && isPackageMod)
{
/* If the previous inserted Package is not yet determined as package.d,
@@ -691,6 +713,8 @@ void Module::parse()
error(pkg->loc, "from file %s conflicts with package name %s",
srcname, pkg->toChars());
}
else
assert(global.errors);
}
else
{
@@ -1071,7 +1095,7 @@ void Module::runDeferredSemantic3()
/************************************
* Recursively look at every module this module imports,
* return TRUE if it imports m.
* return true if it imports m.
* Can be used to detect circular imports.
*/
@@ -1087,7 +1111,7 @@ int Module::imports(Module *m)
for (size_t i = 0; i < aimports.dim; i++)
{ Module *mi = aimports[i];
if (mi == m)
return TRUE;
return true;
if (!mi->insearch)
{
mi->insearch = 1;
@@ -1096,7 +1120,7 @@ int Module::imports(Module *m)
return r;
}
}
return FALSE;
return false;
}
/*************************************
@@ -1191,8 +1215,8 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
if (packages)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = (*packages)[i];
{
Identifier *pid = (*packages)[i];
Package *pkg;
Dsymbol *p = dst->lookup(pid);
if (!p)
@@ -1219,14 +1243,13 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
dst = pkg->symtab;
if (ppkg && !*ppkg)
*ppkg = pkg;
#if 0
if (pkg->isModule())
{ // Return the module so that a nice error message can be generated
{
// Return the module so that a nice error message can be generated
if (ppkg)
*ppkg = (Package *)p;
break;
}
#endif
}
}
if (pparent)
+6 -5
View File
@@ -81,6 +81,7 @@ public:
static AggregateDeclaration *moduleinfo;
const char *arg; // original argument name
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
File *srcfile; // input source file
@@ -88,7 +89,6 @@ public:
File *hdrfile; // 'header' file
File *symfile; // output symbol file
File *docfile; // output documentation file
unsigned errors; // if any errors in file
unsigned numlines; // number of lines in source file
int isDocFile; // if it is a documentation input file, not D source
@@ -122,10 +122,10 @@ public:
size_t nameoffset; // offset of module name from start of ModuleInfo
size_t namelen; // length of module name in characters
int doDocComment; // enable generating doc comments for this module
int doHdrGen; // enable generating header file for this module
bool doDocComment; // enable generating doc comments for this module
bool doHdrGen; // enable generating header file for this module
Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen);
Module(const char *arg, Identifier *ident, int doDocComment, int doHdrGen);
~Module();
static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
@@ -199,12 +199,13 @@ public:
#endif
void genmoduleinfo();
Module *isModule() { return this; }
#if IN_LLVM
// LDC
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
void buildTargetFiles(bool singleObj);
File* buildFilePath(const char* forcename, const char* path, const char* ext);
Module *isModule() { return this; }
llvm::GlobalVariable* moduleInfoSymbol();
bool llvmForceLogging;
+303 -238
View File
File diff suppressed because it is too large Load Diff
+35 -40
View File
@@ -116,8 +116,6 @@ enum ENUMTY
};
typedef unsigned char TY; // ENUMTY
#define Tascii Tchar
extern int Tsize_t;
extern int Tptrdiff_t;
@@ -267,13 +265,13 @@ public:
#if CPP_MANGLE
virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
virtual int isintegral();
virtual int isfloating(); // real, imaginary, or complex
virtual int isreal();
virtual int isimaginary();
virtual int iscomplex();
virtual int isscalar();
virtual int isunsigned();
virtual bool isintegral();
virtual bool isfloating(); // real, imaginary, or complex
virtual bool isreal();
virtual bool isimaginary();
virtual bool iscomplex();
virtual bool isscalar();
virtual bool isunsigned();
virtual int isscope();
virtual int isString();
virtual int isAssignable();
@@ -432,13 +430,13 @@ public:
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
int isintegral();
int isfloating();
int isreal();
int isimaginary();
int iscomplex();
int isscalar();
int isunsigned();
bool isintegral();
bool isfloating();
bool isreal();
bool isimaginary();
bool iscomplex();
bool isscalar();
bool isunsigned();
MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
@@ -471,10 +469,10 @@ public:
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
int isintegral();
int isfloating();
int isscalar();
int isunsigned();
bool isintegral();
bool isfloating();
bool isscalar();
bool isunsigned();
int checkBoolean();
MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc);
@@ -633,7 +631,7 @@ public:
void toJson(JsonOut *json);
MATCH implicitConvTo(Type *to);
MATCH constConv(Type *to);
int isscalar();
bool isscalar();
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -953,13 +951,13 @@ public:
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
Expression *getProperty(Loc loc, Identifier *ident, int flag);
int isintegral();
int isfloating();
int isreal();
int isimaginary();
int iscomplex();
int isscalar();
int isunsigned();
bool isintegral();
bool isfloating();
bool isreal();
bool isimaginary();
bool iscomplex();
bool isscalar();
bool isunsigned();
int checkBoolean();
int isString();
int isAssignable();
@@ -1003,13 +1001,13 @@ public:
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
structalign_t alignment();
Expression *getProperty(Loc loc, Identifier *ident, int flag);
int isintegral();
int isfloating();
int isreal();
int isimaginary();
int iscomplex();
int isscalar();
int isunsigned();
bool isintegral();
bool isfloating();
bool isreal();
bool isimaginary();
bool iscomplex();
bool isscalar();
bool isunsigned();
int checkBoolean();
int isAssignable();
int needsDestruction();
@@ -1131,7 +1129,7 @@ public:
MATCH implicitConvTo(Type *to);
int checkBoolean();
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
d_uns64 size(Loc loc);
@@ -1171,16 +1169,13 @@ public:
static int foreach(Parameters *args, ForeachDg dg, void *ctx, size_t *pn=NULL);
};
extern int Tsize_t;
extern int Tptrdiff_t;
int arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2);
void MODtoBuffer(OutBuffer *buf, unsigned char mod);
char *MODtoChars(unsigned char mod);
int MODimplicitConv(unsigned char modfrom, unsigned char modto);
int MODmethodConv(unsigned char modfrom, unsigned char modto);
int MODmerge(unsigned char mod1, unsigned char mod2);
unsigned char MODmerge(unsigned char mod1, unsigned char mod2);
void identifierToDocBuffer(Identifier* ident, OutBuffer *buf, HdrGenState *hgs);
#endif /* DMD_MTYPE_H */
+9 -40
View File
@@ -13,11 +13,6 @@
#include <ctype.h>
#include <assert.h>
#include <string.h> // memset()
#if _MSC_VER || IN_LLVM // complex.h breaks LLVM headers.
#include <complex>
#else
#include <complex.h>
#endif
#ifdef __APPLE__
#define integer_t dmd_integer_t
@@ -50,7 +45,7 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flag
int Expression::isCommutative()
{
return FALSE; // default is no reverse
return false; // default is no reverse
}
/***********************************
@@ -90,14 +85,14 @@ Identifier *PostExp::opId() { return (op == TOKplusplus)
? Id::postinc
: Id::postdec; }
int AddExp::isCommutative() { return TRUE; }
int AddExp::isCommutative() { return true; }
Identifier *AddExp::opId() { return Id::add; }
Identifier *AddExp::opId_r() { return Id::add_r; }
Identifier *MinExp::opId() { return Id::sub; }
Identifier *MinExp::opId_r() { return Id::sub_r; }
int MulExp::isCommutative() { return TRUE; }
int MulExp::isCommutative() { return true; }
Identifier *MulExp::opId() { return Id::mul; }
Identifier *MulExp::opId_r() { return Id::mul_r; }
@@ -107,10 +102,8 @@ Identifier *DivExp::opId_r() { return Id::div_r; }
Identifier *ModExp::opId() { return Id::mod; }
Identifier *ModExp::opId_r() { return Id::mod_r; }
#if DMDV2
Identifier *PowExp::opId() { return Id::pow; }
Identifier *PowExp::opId_r() { return Id::pow_r; }
#endif
Identifier *ShlExp::opId() { return Id::shl; }
Identifier *ShlExp::opId_r() { return Id::shl_r; }
@@ -121,15 +114,15 @@ Identifier *ShrExp::opId_r() { return Id::shr_r; }
Identifier *UshrExp::opId() { return Id::ushr; }
Identifier *UshrExp::opId_r() { return Id::ushr_r; }
int AndExp::isCommutative() { return TRUE; }
int AndExp::isCommutative() { return true; }
Identifier *AndExp::opId() { return Id::iand; }
Identifier *AndExp::opId_r() { return Id::iand_r; }
int OrExp::isCommutative() { return TRUE; }
int OrExp::isCommutative() { return true; }
Identifier *OrExp::opId() { return Id::ior; }
Identifier *OrExp::opId_r() { return Id::ior_r; }
int XorExp::isCommutative() { return TRUE; }
int XorExp::isCommutative() { return true; }
Identifier *XorExp::opId() { return Id::ixor; }
Identifier *XorExp::opId_r() { return Id::ixor_r; }
@@ -151,10 +144,10 @@ Identifier *UshrAssignExp::opId() { return Id::ushrass; }
Identifier * CatAssignExp::opId() { return Id::catass; }
Identifier * PowAssignExp::opId() { return Id::powass; }
int EqualExp::isCommutative() { return TRUE; }
int EqualExp::isCommutative() { return true; }
Identifier *EqualExp::opId() { return Id::eq; }
int CmpExp::isCommutative() { return TRUE; }
int CmpExp::isCommutative() { return true; }
Identifier *CmpExp::opId() { return Id::cmp; }
Identifier *ArrayExp::opId() { return Id::index; }
@@ -219,7 +212,6 @@ Expression *UnaExp::op_overload(Scope *sc)
{
//printf("UnaExp::op_overload() (%s)\n", toChars());
#if DMDV2
if (e1->op == TOKarray)
{
ArrayExp *ae = (ArrayExp *)e1;
@@ -311,7 +303,6 @@ Expression *UnaExp::op_overload(Scope *sc)
att1 = NULL;
}
}
#endif
e1 = e1->semantic(sc);
e1 = resolveProperties(sc, e1);
@@ -345,7 +336,6 @@ Expression *UnaExp::op_overload(Scope *sc)
}
#endif
#if DMDV2
/* Rewrite as:
* e1.opUnary!("+")();
*/
@@ -373,7 +363,6 @@ Expression *UnaExp::op_overload(Scope *sc)
ue->e1 = e1;
return ue->trySemantic(sc);
}
#endif
}
return NULL;
}
@@ -501,7 +490,6 @@ Expression *BinExp::op_overload(Scope *sc)
#endif
Objects *tiargs = NULL;
#if DMDV2
if (op == TOKplusplus || op == TOKminusminus)
{ // Bug4099 fix
if (ad1 && search_function(ad1, Id::opUnary))
@@ -537,7 +525,6 @@ Expression *BinExp::op_overload(Scope *sc)
tiargs = opToArg(sc, op);
}
}
#endif
if (s || s_r)
{
@@ -692,7 +679,6 @@ L1:
}
#endif
#if DMDV2
// Try alias this on first operand
if (ad1 && ad1->aliasthis &&
!(op == TOKassign && ad2 && ad1 == ad2)) // See Bugzilla 2943
@@ -731,7 +717,6 @@ L1:
be->e2 = e2;
return be->trySemantic(sc);
}
#endif
return NULL;
}
@@ -948,7 +933,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
{
//printf("BinAssignExp::op_overload() (%s)\n", toChars());
#if DMDV2
if (e1->op == TOKarray)
{
ArrayExp *ae = (ArrayExp *)e1;
@@ -1045,7 +1029,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
att1 = NULL;
}
}
#endif
BinExp::semantic(sc);
e1 = resolveProperties(sc, e1);
@@ -1071,7 +1054,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
#endif
Objects *tiargs = NULL;
#if DMDV2
if (!s)
{ /* Try the new D2 scheme, opOpAssign
*/
@@ -1091,7 +1073,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
tiargs = opToArg(sc, op);
}
}
#endif
if (s)
{
@@ -1131,7 +1112,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
L1:
#if DMDV2
// Try alias this on first operand
if (ad1 && ad1->aliasthis)
{
@@ -1166,7 +1146,6 @@ L1:
be->e2 = e2;
return be->trySemantic(sc);
}
#endif
return NULL;
}
@@ -1226,10 +1205,8 @@ Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
{
Identifier *idapply = (op == TOKforeach) ? Id::apply : Id::applyReverse;
#if DMDV2
Identifier *idfront = (op == TOKforeach) ? Id::Ffront : Id::Fback;
int sliced = 0;
#endif
Type *tab;
Type *att = NULL;
Expression *org_aggr = aggr;
@@ -1265,7 +1242,6 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
goto Laggr;
Laggr:
#if DMDV2
if (!sliced)
{
sapply = search_function(ad, idapply);
@@ -1298,13 +1274,6 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
aggr = new DotIdExp(aggr->loc, aggr, ad->aliasthis->ident);
continue;
}
#else
sapply = search_function(ad, idapply);
if (sapply)
{ // opApply aggregate
break;
}
#endif
goto Lerr;
case Tdelegate:
@@ -1488,7 +1457,7 @@ static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart,
struct ParamOpOver
{
Parameters *arguments;
int mod;
unsigned char mod;
MATCH match;
FuncDeclaration *fd_best;
FuncDeclaration *fd_ambig;
+16 -21
View File
@@ -13,10 +13,6 @@
#include <assert.h>
#include <math.h>
#if __DMC__
#include <complex.h>
#endif
#include "lexer.h"
#include "mtype.h"
#include "expression.h"
@@ -421,7 +417,7 @@ Expression *PtrExp::optimize(int result, bool keepLvalue)
Expression *e = expandVar(result, v);
if (e && e->op == TOKstructliteral)
{ StructLiteralExp *sle = (StructLiteralExp *)e;
e = sle->getField(type, se->offset);
e = sle->getField(type, (unsigned)se->offset);
if (e && e != EXP_CANT_INTERPRET)
return e;
}
@@ -449,7 +445,7 @@ Expression *DotVarExp::optimize(int result, bool keepLvalue)
VarDeclaration *vf = var->isVarDeclaration();
if (vf)
{
Expression *e = sle->getField(type, vf->offset);
e = sle->getField(type, vf->offset);
if (e && e != EXP_CANT_INTERPRET)
return e;
}
@@ -489,7 +485,6 @@ Expression *NewExp::optimize(int result, bool keepLvalue)
Expression *CallExp::optimize(int result, bool keepLvalue)
{
//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
Expression *e = this;
// Optimize parameters with keeping lvalue-ness
if (arguments)
@@ -502,9 +497,9 @@ Expression *CallExp::optimize(int result, bool keepLvalue)
for (size_t i = 0; i < arguments->dim; i++)
{
Parameter *p = Parameter::getNth(tf->parameters, i);
bool keepLvalue = (p ? (p->storageClass & (STCref | STCout)) != 0 : false);
bool keep = (p ? (p->storageClass & (STCref | STCout)) != 0 : false);
Expression *e = (*arguments)[i];
e = e->optimize(WANTvalue, keepLvalue);
e = e->optimize(WANTvalue, keep);
(*arguments)[i] = e;
}
}
@@ -513,6 +508,7 @@ Expression *CallExp::optimize(int result, bool keepLvalue)
if (keepLvalue)
return this;
Expression *e = this;
#if 1
#else
if (e1->op == TOKvar)
@@ -573,7 +569,10 @@ Expression *CastExp::optimize(int result, bool keepLvalue)
e1->type->implicitConvTo(type) >= MATCHconst)
{
if (X) printf(" returning2 %s\n", e1->toChars());
goto L1;
L1: // Returning e1 with changing its type
Expression *e = (e1old == e1 ? e1->copy() : e1);
e->type = type;
return e;
}
/* The first test here is to prevent infinite loops
@@ -632,10 +631,6 @@ Expression *CastExp::optimize(int result, bool keepLvalue)
e = this;
if (X) printf(" returning6 %s\n", e->toChars());
return e;
L1: // Returning e1 with changing its type
e = (e1old == e1 ? e1->copy() : e1);
e->type = type;
return e;
#undef X
}
@@ -1034,7 +1029,7 @@ void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr)
{
Type *t = arr->type->toBasetype();
if (t->ty == Tsarray)
len = ((TypeSArray *)t)->dim->toInteger();
len = (size_t)((TypeSArray *)t)->dim->toInteger();
else
return; // we don't know the length yet
}
@@ -1100,7 +1095,7 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue)
if (e1->op == TOKerror)
return e1;
e = this;
if (e1->isBool(FALSE))
if (e1->isBool(false))
{
if (type->toBasetype()->ty == Tvoid)
e = e2;
@@ -1126,7 +1121,7 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue)
e = new IntegerExp(loc, n1 && n2, type);
}
else if (e1->isBool(TRUE))
else if (e1->isBool(true))
{
if (type->toBasetype()->ty == Tvoid)
e = e2;
@@ -1144,7 +1139,7 @@ Expression *OrOrExp::optimize(int result, bool keepLvalue)
if (e1->op == TOKerror)
return e1;
e = this;
if (e1->isBool(TRUE))
if (e1->isBool(true))
{ // Replace with (e1, 1)
e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
e->type = type;
@@ -1166,7 +1161,7 @@ Expression *OrOrExp::optimize(int result, bool keepLvalue)
e = new IntegerExp(loc, n1 || n2, type);
}
else if (e1->isBool(FALSE))
else if (e1->isBool(false))
{
if (type->toBasetype()->ty == Tvoid)
e = e2;
@@ -1211,9 +1206,9 @@ Expression *CondExp::optimize(int result, bool keepLvalue)
{ Expression *e;
econd = econd->optimize(WANTflags);
if (econd->isBool(TRUE))
if (econd->isBool(true))
e = e1->optimize(result, keepLvalue);
else if (econd->isBool(FALSE))
else if (econd->isBool(false))
e = e2->optimize(result, keepLvalue);
else
{ e1 = e1->optimize(result, keepLvalue);
+157 -277
View File
File diff suppressed because it is too large Load Diff
+7 -10
View File
@@ -69,18 +69,19 @@ public:
int inBrackets; // inside [] of array index or slice
Loc lookingForElse; // location of lonely if looking for an else
Parser(Module *module, utf8_t *base, size_t length, int doDocComment);
Parser(Loc loc, Module *module, const utf8_t *base, size_t length, int doDocComment);
Parser(Module *module, const utf8_t *base, size_t length, int doDocComment);
Dsymbols *parseModule();
Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL);
Dsymbols *parseAutoDeclarations(StorageClass storageClass, utf8_t *comment);
Dsymbols *parseAutoDeclarations(StorageClass storageClass, const utf8_t *comment);
Dsymbols *parseBlock(Dsymbol **pLastDecl);
void composeStorageClass(StorageClass stc);
StorageClass parseAttribute(Expressions **pexps);
StorageClass parsePostfix();
StorageClass parseTypeCtor();
Expression *parseConstraint();
TemplateDeclaration *parseTemplateDeclaration(int ismixin);
TemplateDeclaration *parseTemplateDeclaration(bool ismixin = false);
TemplateParameters *parseTemplateParameterList(int flag = 0);
Dsymbol *parseMixin();
Objects *parseTemplateArgumentList();
@@ -112,11 +113,11 @@ public:
Type *parseBasicType();
Type *parseBasicType2(Type *t);
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int* pdisable = NULL);
Dsymbols *parseDeclarations(StorageClass storage_class, utf8_t *comment);
Dsymbols *parseDeclarations(StorageClass storage_class, const utf8_t *comment);
void parseContracts(FuncDeclaration *f);
void checkDanglingElse(Loc elseloc);
/** endPtr used for documented unittests */
Statement *parseStatement(int flags, utf8_t** endPtr = NULL);
Statement *parseStatement(int flags, const utf8_t** endPtr = NULL);
Initializer *parseInitializer();
Expression *parseDefaultInitExp();
void check(Loc loc, TOK value);
@@ -138,10 +139,6 @@ public:
Expression *parseMulExp();
Expression *parseAddExp();
Expression *parseShiftExp();
#if DMDV1
Expression *parseRelExp();
Expression *parseEqualExp();
#endif
Expression *parseCmpExp();
Expression *parseAndExp();
Expression *parseXorExp();
@@ -155,7 +152,7 @@ public:
Expression *parseNewExp(Expression *thisexp);
void addComment(Dsymbol *s, utf8_t *blockComment);
void addComment(Dsymbol *s, const utf8_t *blockComment);
};
// Operator precedence - greater values are higher precedence
-499
View File
@@ -1,499 +0,0 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include <unistd.h>
#include <pthread.h>
#endif
#include "rmem.h"
#include "gc/gc.h"
//#include "printf.h"
/* This implementation of the storage allocator uses the Digital Mars gc.
*/
Mem mem;
//static int nuncollectable;
extern "C"
{
void gc_init();
GC *gc_get();
}
void Mem::init()
{
gc_init();
}
char *Mem::strdup(const char *s)
{
return gc_get()->strdup(s);
}
void *Mem::malloc(size_t size)
{
if (gc) // if cached allocator
{
// PRINTF("Using cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
// GC::file = NULL;
// GC::line = 0;
return ((GC *)gc)->malloc(size);
}
if (this == &mem) // don't cache global mem
{
// PRINTF("Using global gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
// GC::file = NULL;
// GC::line = 0;
return gc_get()->malloc(size);
}
// PRINTF("Generating cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
gc = gc_get();
return gc->malloc(size);
}
void *Mem::malloc_uncollectable(size_t size)
{ void *p;
p = ::malloc(size);
if (!p)
error();
addroots((char *)p, (char *)p + size);
#if 0
++nuncollectable;
WPRINTF(L"malloc_uncollectable(%u) = %x, n=%d\n", size, p, nuncollectable);
#endif
return p;
}
void *Mem::calloc(size_t size, size_t n)
{
return gc_get()->calloc(size, n);
}
void *Mem::realloc(void *p, size_t size)
{
return gc_get()->realloc(p, size);
}
void Mem::free(void *p)
{
gc_get()->free(p);
}
void Mem::free_uncollectable(void *p)
{
if (p)
{ removeroots((char *)p);
::free(p);
#if 0
--nuncollectable;
WPRINTF(L"free_uncollectable(%x) n=%d\n", p, nuncollectable);
#endif
#if 0
gc_get()->fullcollect();
GCStats stats;
getStats(&stats);
WPRINTF(L"poolsize = %x, usedsize = %x, freelistsize = %x\n",
stats.poolsize, stats.usedsize, stats.freelistsize);
#endif
}
}
void *Mem::mallocdup(void *o, size_t size)
{
return gc_get()->mallocdup(o, size);
}
void Mem::check(void *p)
{
if (gc)
gc->check(p);
else
gc_get()->check(p);
}
void Mem::error()
{
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
assert(0);
#endif
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
gc_get()->fullcollect();
#if 0
{
GCStats stats;
gc_get()->getStats(&stats);
WPRINTF(L"Thread %x ", Thread::getId());
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
}
#endif
}
void Mem::fullcollectNoStack()
{
gc_get()->fullcollectNoStack();
#if 0
{
GCStats stats;
gc_get()->getStats(&stats);
WPRINTF(L"Thread %x ", Thread::getId());
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
}
#endif
}
void Mem::mark(void *pointer)
{
(void) pointer; // for VC /W4 compatibility
}
void Mem::addroots(char* pStart, char* pEnd)
{
gc_get()->addRange(pStart, pEnd);
}
void Mem::removeroots(char* pStart)
{
gc_get()->removeRange(pStart);
}
void Mem::setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData)
{
(void)pClientData;
gc_get()->setFinalizer(pObj, pFn);
}
void Mem::setStackBottom(void *stackbottom)
{
gc_get()->setStackBottom(stackbottom);
}
GC *Mem::getThreadGC()
{
return gc_get();
}
/* =================================================== */
#if 1
void * operator new(size_t m_size)
{
//PRINTF("Call to global operator new(%d), file = '%s', line = %d\n", m_size, GC::file ? GC::file : "(null)", GC::line);
GC::file = NULL;
GC::line = 0;
return mem.malloc(m_size);
}
void operator delete(void *p)
{
//WPRINTF(L"Call to global operator delete\n");
mem.free(p);
}
void* operator new[](size_t size)
{
return operator new(size);
}
void operator delete[](void *pv)
{
operator delete(pv);
}
#endif
void * Mem::operator new(size_t m_size)
{ void *p;
p = gc_get()->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
mem.error();
return p;
}
void * Mem::operator new(size_t m_size, Mem *mem)
{ void *p;
p = mem->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
::mem.error();
return p;
}
void * Mem::operator new(size_t m_size, GC *gc)
{ void *p;
// if (!gc)
// WPRINTF(L"gc is NULL\n");
p = gc->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
::mem.error();
return p;
}
void Mem::operator delete(void *p)
{
// printf("Mem::operator delete(%p)\n", p);
gc_get()->free(p);
}
/* ============================================================ */
/* The following section of code exists to find the right
* garbage collector for this thread. There is one independent instance
* of the collector per thread.
*/
/* ===================== linux ================================ */
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
#include <pthread.h>
#define LOG 0 // log thread creation / destruction
extern "C"
{
// Key identifying the thread-specific data
static pthread_key_t gc_key;
/* "Once" variable ensuring that the key for gc_alloc will be allocated
* exactly once.
*/
static pthread_once_t gc_alloc_key_once = PTHREAD_ONCE_INIT;
/* Forward functions */
static void gc_alloc_key();
static void gc_alloc_destroy_gc(void * accu);
void gc_init()
{
#if LOG
WPRINTF(L"Thread %lx: gc_init()\n", pthread_self());
#endif
pthread_once(&gc_alloc_key_once, gc_alloc_key);
#if LOG
WPRINTF(L"Thread %lx: gc_init() return\n", pthread_self());
#endif
}
GC *gc_get()
{
GC *gc;
// Get the thread-specific data associated with the key
gc = (GC *) pthread_getspecific(gc_key);
// It's initially NULL, meaning that we must allocate the buffer first.
if (gc == NULL)
{
GC_LOG();
gc = new GC();
gc->init();
// Store the buffer pointer in the thread-specific data.
pthread_setspecific(gc_key, (void *) gc);
#if LOG
WPRINTF(L"Thread %lx: allocating gc at %x\n", pthread_self(), gc);
#endif
}
return gc;
}
// Function to allocate the key for gc_alloc thread-specific data.
static void gc_alloc_key()
{
pthread_key_create(&gc_key, gc_alloc_destroy_gc);
#if LOG
WPRINTF(L"Thread %lx: allocated gc key %d\n", pthread_self(), gc_key);
#endif
}
// Function to free the buffer when the thread exits.
// Called only when the thread-specific data is not NULL.
static void gc_alloc_destroy_gc(void *gc)
{
#if LOG
WPRINTF(L"Thread %x: freeing gc at %x\n", pthread_self(), gc);
#endif
delete (GC *)gc;
}
}
#endif
/* ===================== win32 ================================ */
#if !defined(linux) && defined(_WIN32)
#if 1 // single threaded version
extern "C"
{
static GC *gc;
void gc_init()
{
if (!gc)
{ gc = (GC *)::malloc(sizeof(GC));
gc->init();
}
}
GC *gc_get()
{
return gc;
}
}
#else // multi threaded version
#include "mutex.h"
#include "thread.h"
/* This is the win32 version. It suffers from the bug that
* when the thread exits the data structure is not cleared,
* but the memory pool it points to is free'd.
* Thus, if a new thread comes along with the same thread id,
* the data will look initialized, but will point to garbage.
*
* What needs to happen is when a thread exits, the associated
* GC_context data struct is cleared.
*/
struct GC_context
{
ThreadId threadid; // identifier of current thread
GC *gc;
};
Mutex gc_mutex;
static GC_context array[64];
// Array of pointers to GC_context objects, one per threadid
GC_context *gccontext = array;
unsigned gccontext_allocdim = 64;
unsigned gccontext_dim;
ThreadId gc_cache_ti;
GC_context *gc_cache_cc;
extern "C" void gc_init()
{
}
extern "C" GC *gc_get()
{
/* This works by creating an array of GC_context's, one
* for each thread. We match up by thread id.
*/
ThreadId ti;
GC_context *cc;
//PRINTF("gc_get()\n");
ti = Thread::getId();
gc_mutex.acquire();
// Used cached version if we can
if (ti == gc_cache_ti)
{
cc = gc_cache_cc;
//exception(L"getGC_context(): cache x%x", ti);
}
else
{
// This does a linear search through gccontext[].
// A hash table might be faster if there are more
// than a dozen threads.
GC_context *ccp;
GC_context *ccptop = &gccontext[gccontext_dim];
for (ccp = gccontext; ccp < ccptop; ccp++)
{
cc = ccp;
if (cc->threadid == ti)
{
WPRINTF(L"getGC_context(): existing x%x", ti);
goto Lret;
}
}
// Do not allocate with garbage collector, as this must reside
// global to all threads.
assert(gccontext_dim < gccontext_allocdim);
cc = ccp;
memset(cc, 0, sizeof(*cc));
cc->threadid = ti;
cc->gc = new GC();
cc->gc->init();
gccontext_dim++;
WPRINTF(L"getGC_context(): new x%x\n", ti);
Lret:
// Cache for next time
gc_cache_ti = ti;
gc_cache_cc = cc;
}
gc_mutex.release();
return cc->gc;
}
#endif
#endif
+11 -9
View File
@@ -520,6 +520,16 @@ int ld_type(longdouble x)
size_t ld_sprint(char* str, int fmt, longdouble x)
{
// ensure dmc compatible strings for nan and inf
switch(ld_type(x))
{
case LD_TYPE_QNAN:
case LD_TYPE_SNAN:
return sprintf(str, "nan");
case LD_TYPE_INFINITE:
return sprintf(str, x.sign ? "-inf" : "inf");
}
// fmt is 'a','A','f' or 'g'
if(fmt != 'a' && fmt != 'A')
{
@@ -537,16 +547,8 @@ size_t ld_sprint(char* str, int fmt, longdouble x)
unsigned short exp = x.exponent;
unsigned long long mantissa = x.mantissa;
switch(ld_type(x))
{
case LD_TYPE_ZERO:
if(ld_type(x) == LD_TYPE_ZERO)
return sprintf(str, "0x0.0L");
case LD_TYPE_QNAN:
case LD_TYPE_SNAN:
return sprintf(str, "NAN");
case LD_TYPE_INFINITE:
return sprintf(str, x.sign ? "-INF" : "INF");
}
size_t len = 0;
if(x.sign)
+1 -1
View File
@@ -763,7 +763,7 @@ int Port::isInfinity(double r)
longdouble Port::fmodl(longdouble x, longdouble y)
{
#if __FreeBSD__ || __OpenBSD__
#if __FreeBSD__ && __FreeBSD_version < 800000 || __OpenBSD__
return ::fmod(x, y); // hack for now, fix later
#else
return ::fmodl(x, y);
-22
View File
@@ -18,10 +18,6 @@
Mem mem;
void Mem::init()
{
}
char *Mem::strdup(const char *s)
{
char *p;
@@ -118,24 +114,6 @@ void Mem::error()
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
}
void Mem::mark(void *pointer)
{
(void) pointer; // necessary for VC /W4
}
void Mem::setStackBottom(void *bottom)
{
}
void Mem::addroots(char* pStart, char* pEnd)
{
}
/* =================================================== */
#if defined(__has_feature)
+1 -28
View File
@@ -15,44 +15,17 @@
#endif
#include <stddef.h> // for size_t
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
struct GC; // thread specific allocator
struct Mem
{
GC *gc; // pointer to our thread specific allocator
Mem() { gc = NULL; }
void init();
// Derive from Mem to get these storage allocators instead of global new/delete
void * operator new(size_t m_size);
void * operator new(size_t m_size, Mem *mem);
void * operator new(size_t m_size, GC *gc);
void operator delete(void *p);
void * operator new[](size_t m_size);
void operator delete[](void *p);
Mem() { }
char *strdup(const char *s);
void *malloc(size_t size);
void *malloc_uncollectable(size_t size);
void *calloc(size_t size, size_t n);
void *realloc(void *p, size_t size);
void free(void *p);
void free_uncollectable(void *p);
void *mallocdup(void *o, size_t size);
void error();
void check(void *p); // validate pointer
void fullcollect(); // do full garbage collection
void fullcollectNoStack(); // do full garbage collection, no scan stack
void mark(void *pointer);
void addroots(char* pStart, char* pEnd);
void removeroots(char* pStart);
void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
void setStackBottom(void *bottom);
GC *getThreadGC(); // get apartment allocator for this thread
};
extern Mem mem;
+9 -254
View File
@@ -103,11 +103,6 @@ bool RootObject::equals(RootObject *o)
return o == this;
}
hash_t RootObject::hashCode()
{
return (hash_t) this;
}
int RootObject::compare(RootObject *obj)
{
return this - obj;
@@ -133,104 +128,10 @@ void RootObject::toBuffer(OutBuffer *b)
b->writestring("Object");
}
void RootObject::mark()
{
}
/****************************** String ********************************/
String::String(const char *str)
: str(mem.strdup(str))
{
}
String::~String()
{
mem.free((void *)str);
}
void String::mark()
{
mem.mark((void *)str);
}
hash_t String::calcHash(const char *str, size_t len)
{
hash_t hash = 0;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(uint8_t *)str;
return hash;
case 2:
hash *= 37;
hash += *(uint16_t *)str;
return hash;
case 3:
hash *= 37;
hash += (*(uint16_t *)str << 8) +
((uint8_t *)str)[2];
return hash;
default:
hash *= 37;
hash += *(uint32_t *)str;
str += 4;
len -= 4;
break;
}
}
}
hash_t String::calcHash(const char *str)
{
return calcHash(str, strlen(str));
}
hash_t String::hashCode()
{
return calcHash(str, strlen(str));
}
size_t String::len()
{
return strlen(str);
}
bool String::equals(RootObject *obj)
{
return strcmp(str,((String *)obj)->str) == 0;
}
int String::compare(RootObject *obj)
{
return strcmp(str,((String *)obj)->str);
}
char *String::toChars()
{
return (char *)str; // toChars() should really be const
}
void String::print()
{
printf("String '%s'\n",str);
}
/****************************** FileName ********************************/
FileName::FileName(const char *str)
: String(str)
: str(mem.strdup(str))
{
}
@@ -339,51 +240,6 @@ Strings *FileName::splitPath(const char *path)
return array;
}
hash_t FileName::hashCode()
{
#if _WIN32
// We need a different hashCode because it must be case-insensitive
size_t len = strlen(str);
hash_t hash = 0;
utf8_t *s = (utf8_t *)str;
for (;;)
{
switch (len)
{
case 0:
return hash;
case 1:
hash *= 37;
hash += *(uint8_t *)s | 0x20;
return hash;
case 2:
hash *= 37;
hash += *(uint16_t *)s | 0x2020;
return hash;
case 3:
hash *= 37;
hash += ((*(uint16_t *)s << 8) +
((uint8_t *)s)[2]) | 0x202020;
break;
default:
hash *= 37;
hash += *(uint32_t *)s | 0x20202020;
s += 4;
len -= 4;
break;
}
}
#else
// darwin HFS is case insensitive, though...
return String::hashCode();
#endif
}
int FileName::compare(RootObject *obj)
{
return compare(str, ((FileName *)obj)->str);
@@ -941,6 +797,11 @@ void FileName::free(const char *str)
mem.free((void *)str);
}
char *FileName::toChars()
{
return (char *)str; // toChars() should really be const
}
/****************************** File ********************************/
@@ -969,7 +830,7 @@ File::~File()
if (ref == 0)
mem.free(buffer);
#if _WIN32
else if (ref == 2)
if (ref == 2)
UnmapViewOfFile(buffer);
#endif
}
@@ -977,13 +838,6 @@ File::~File()
mem.free(touchtime);
}
void File::mark()
{
mem.mark(buffer);
mem.mark(touchtime);
mem.mark(name);
}
/*************************************
*/
@@ -1394,9 +1248,9 @@ Files *File::match(FileName *n)
char *fn;
File *f;
fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1);
fn = (char *)mem.malloc(name - c + strlen(&fileinfo.cFileName[0]) + 1);
memcpy(fn, c, name - c);
strcpy(fn + (name - c), fileinfo.cFileName);
strcpy(fn + (name - c), &fileinfo.cFileName[0]);
f = new File(fn);
f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
@@ -1490,11 +1344,6 @@ char *OutBuffer::extractData()
return p;
}
void OutBuffer::mark()
{
mem.mark(data);
}
void OutBuffer::reserve(size_t nbytes)
{
//printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
@@ -1861,97 +1710,3 @@ char *OutBuffer::toChars()
writeByte(0);
return (char *)data;
}
// TODO: Remove (only used by disabled GC)
/********************************* Bits ****************************/
Bits::Bits()
{
data = NULL;
bitdim = 0;
allocdim = 0;
}
Bits::~Bits()
{
mem.free(data);
}
void Bits::mark()
{
mem.mark(data);
}
void Bits::resize(unsigned bitdim)
{
unsigned allocdim;
unsigned mask;
allocdim = (bitdim + 31) / 32;
data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0]));
if (this->allocdim < allocdim)
memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0]));
// Clear other bits in last word
mask = (1 << (bitdim & 31)) - 1;
if (mask)
data[allocdim - 1] &= ~mask;
this->bitdim = bitdim;
this->allocdim = allocdim;
}
void Bits::set(unsigned bitnum)
{
data[bitnum / 32] |= 1 << (bitnum & 31);
}
void Bits::clear(unsigned bitnum)
{
data[bitnum / 32] &= ~(1 << (bitnum & 31));
}
int Bits::test(unsigned bitnum)
{
return data[bitnum / 32] & (1 << (bitnum & 31));
}
void Bits::set()
{ unsigned mask;
memset(data, ~0, allocdim * sizeof(data[0]));
// Clear other bits in last word
mask = (1 << (bitdim & 31)) - 1;
if (mask)
data[allocdim - 1] &= mask;
}
void Bits::clear()
{
memset(data, 0, allocdim * sizeof(data[0]));
}
void Bits::copy(Bits *from)
{
assert(bitdim == from->bitdim);
memcpy(data, from->data, allocdim * sizeof(data[0]));
}
Bits *Bits::clone()
{
Bits *b;
b = new Bits();
b->resize(bitdim);
b->copy(this);
return b;
}
void Bits::sub(Bits *b)
{
unsigned u;
for (u = 0; u < allocdim; u++)
data[u] &= ~b->data[u];
}
+6 -71
View File
@@ -31,8 +31,8 @@ struct OutBuffer;
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct Array;
typedef Array<class File> Files;
typedef Array<char> Strings;
typedef Array<struct File> Files;
typedef Array<const char> Strings;
class RootObject
@@ -43,11 +43,6 @@ public:
virtual bool equals(RootObject *o);
/**
* Returns a hash code, useful for things like building hash tables of Objects.
*/
virtual hash_t hashCode();
/**
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
* Useful for sorting Objects.
@@ -67,38 +62,13 @@ public:
* defined by the library user. For Object, the return value is 0.
*/
virtual int dyncast();
/**
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
*/
/*virtual*/ // not used, disable for now
void mark();
};
class String : public RootObject
{
public:
const char *str; // the string itself
String(const char *str);
~String();
static hash_t calcHash(const char *str, size_t len);
static hash_t calcHash(const char *str);
hash_t hashCode();
size_t len();
bool equals(RootObject *obj);
int compare(RootObject *obj);
char *toChars();
void print();
void mark();
};
class FileName : public String
struct FileName
{
public:
const char *str;
FileName(const char *str);
hash_t hashCode();
bool equals(RootObject *obj);
static int equals(const char *name1, const char *name2);
int compare(RootObject *obj);
@@ -129,9 +99,10 @@ public:
static const char *canonicalName(const char *name);
static void free(const char *str);
char *toChars();
};
class File : public RootObject
struct File
{
public:
int ref; // != 0 if this is a reference to someone else's buffer
@@ -145,8 +116,6 @@ public:
File(const FileName *);
~File();
void mark();
char *toChars();
/* Read file, return !=0 if error
@@ -250,7 +219,6 @@ struct OutBuffer
OutBuffer();
~OutBuffer();
char *extractData();
void mark();
void reserve(size_t nbytes);
void setsize(size_t size);
@@ -308,13 +276,6 @@ struct Array
mem.free(data);
}
void mark()
{
mem.mark(data);
for (size_t u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's?
}
char *toChars()
{
char **buf = (char **)malloc(dim * sizeof(char *));
@@ -522,30 +483,4 @@ struct Array
}
};
// TODO: Remove (only used by disabled GC)
class Bits : public RootObject
{
public:
unsigned bitdim;
unsigned allocdim;
unsigned *data;
Bits();
~Bits();
void mark();
void resize(unsigned bitdim);
void set(unsigned bitnum);
void clear(unsigned bitnum);
int test(unsigned bitnum);
void set();
void clear();
void copy(Bits *from);
Bits *clone();
void sub(Bits *b);
};
#endif
+2 -1
View File
@@ -203,7 +203,8 @@ void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg,
void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset)
{
size_t seedlen = strlen(seed);
for (int distance = 0; distance < 2; distance++)
size_t maxdist = seedlen < 3 ? seedlen - 1 : 2;
for (int distance = 0; distance < maxdist; distance++)
{ void *p = spellerX(seed, seedlen, fp, fparg, charset, distance);
if (p)
return p;
+2 -6
View File
@@ -36,7 +36,7 @@ bool Statement::apply(sapply_fp_t fp, void *param)
/******************************
* Perform apply() on an t if not null
*/
#define scondApply(t, fp, param) (t ? t->apply(fp, param) : 0)
#define scondApply(t, fp, param) (t ? t->apply(fp, param) : false)
@@ -101,13 +101,11 @@ bool ForeachStatement::apply(sapply_fp_t fp, void *param)
(*fp)(this, param);
}
#if DMDV2
bool ForeachRangeStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
#endif
bool IfStatement::apply(sapply_fp_t fp, void *param)
{
@@ -141,13 +139,11 @@ bool CaseStatement::apply(sapply_fp_t fp, void *param)
(*fp)(this, param);
}
#if DMDV2
bool CaseRangeStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
#endif
bool DefaultStatement::apply(sapply_fp_t fp, void *param)
{
@@ -176,7 +172,7 @@ bool TryCatchStatement::apply(sapply_fp_t fp, void *param)
for (size_t i = 0; i < catches->dim; i++)
{ Catch *c = (*catches)[i];
bool r = scondApply(c->handler, fp, param);
r = scondApply(c->handler, fp, param);
if (r)
return r;
}
+31 -11
View File
@@ -57,8 +57,12 @@ Scope::Scope()
this->enclosing = NULL;
this->parent = NULL;
this->sw = NULL;
#if IN_LLVM
this->enclosingFinally = NULL;
this->enclosingScopeExit = NULL;
#else
this->tf = NULL;
#endif
this->tinst = NULL;
this->sbreak = NULL;
this->scontinue = NULL;
@@ -78,6 +82,7 @@ Scope::Scope()
this->noctor = 0;
this->intypeof = 0;
this->speculative = 0;
this->lastVar = NULL;
this->callSuper = 0;
this->fieldinit = NULL;
this->fieldinit_dim = 0;
@@ -99,8 +104,12 @@ Scope::Scope(Scope *enclosing)
this->scopesym = NULL;
this->sd = NULL;
this->sw = enclosing->sw;
#if IN_LLVM
this->enclosingFinally = enclosing->enclosingFinally;
this->enclosingScopeExit = enclosing->enclosingScopeExit;
#else
this->tf = enclosing->tf;
#endif
this->tinst = enclosing->tinst;
this->sbreak = enclosing->sbreak;
this->scontinue = enclosing->scontinue;
@@ -129,10 +138,11 @@ Scope::Scope(Scope *enclosing)
this->noctor = enclosing->noctor;
this->intypeof = enclosing->intypeof;
this->speculative = enclosing->speculative;
this->lastVar = enclosing->lastVar;
this->callSuper = enclosing->callSuper;
this->fieldinit = enclosing->saveFieldInit();
this->fieldinit_dim = enclosing->fieldinit_dim;
this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe));
this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe | SCOPEcompile));
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
@@ -191,7 +201,7 @@ Scope *Scope::pop()
size_t dim = fieldinit_dim;
for (size_t i = 0; i < dim; i++)
enclosing->fieldinit[i] |= fieldinit[i];
delete[] fieldinit;
mem.free(fieldinit);
fieldinit = NULL;
}
}
@@ -277,14 +287,9 @@ unsigned *Scope::saveFieldInit()
if (fieldinit) // copy
{
size_t dim = fieldinit_dim;
fi = new unsigned[dim];
#if IN_LLVM // ASan
memcpy(fi, fieldinit, sizeof(*fi) * dim);
#else
fi[0] = dim;
fi = (unsigned *)mem.malloc(sizeof(unsigned) * dim);
for (size_t i = 0; i < dim; i++)
fi[i] = fieldinit[i];
#endif
}
return fi;
}
@@ -455,9 +460,24 @@ Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
}
Dsymbol *Scope::insert(Dsymbol *s)
{ Scope *sc;
for (sc = this; sc; sc = sc->enclosing)
{
if (VarDeclaration *vd = s->isVarDeclaration())
{
if (lastVar)
vd->lastVar = lastVar;
lastVar = vd;
}
else if (WithScopeSymbol *ss = s->isWithScopeSymbol())
{
if (VarDeclaration *vd = ss->withstate->wthis)
{
if (lastVar)
vd->lastVar = lastVar;
lastVar = vd;
}
return NULL;
}
for (Scope *sc = this; sc; sc = sc->enclosing)
{
//printf("\tsc = %p\n", sc);
if (sc->scopesym)
+2
View File
@@ -64,6 +64,7 @@ enum PROT;
#define SCOPEctfe 0x0080 // inside a ctfe-only expression
#define SCOPEnoaccesscheck 0x0100 // don't do access checks
#define SCOPEcompile 0x0200 // inside __traits(compile)
struct Scope
{
@@ -95,6 +96,7 @@ struct Scope
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
bool speculative; // in __traits(compiles) or typeof(exp)
VarDeclaration *lastVar; // Previous symbol used to prevent goto-skips-init
unsigned callSuper; // primitive flow analysis for constructors
unsigned *fieldinit;
+5 -5
View File
@@ -31,7 +31,7 @@ int lambdaHasSideEffect(Expression *e, void *param);
bool Expression::hasSideEffect()
{
bool has = FALSE;
bool has = false;
apply(&lambdaHasSideEffect, &has);
return has;
}
@@ -68,7 +68,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
case TOKdelete:
case TOKnew:
case TOKnewanonclass:
*phas = TRUE;
*phas = true;
break;
case TOKcall:
@@ -89,7 +89,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
{
}
else
*phas = TRUE;
*phas = true;
}
break;
}
@@ -101,7 +101,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
* cast(classtype)func() // because it may throw
*/
if (ce->to->ty == Tclass && ce->e1->op == TOKcall && ce->e1->type->ty == Tclass)
*phas = TRUE;
*phas = true;
break;
}
@@ -118,7 +118,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
*/
void Expression::discardValue()
{
bool has = FALSE;
bool has = false;
lambdaHasSideEffect(this, &has);
if (!has)
{
+275 -229
View File
File diff suppressed because it is too large Load Diff
+9 -8
View File
@@ -326,6 +326,7 @@ public:
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
ScopeStatement *isScopeStatement() { return this; }
ReturnStatement *isReturnStatement();
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
@@ -434,7 +435,7 @@ public:
FuncDeclaration *func; // function we're lexically in
Statements *cases; // put breaks, continues, gotos and returns here
CompoundStatements *gotos; // forward referenced goto's go here
ScopeStatements *gotos; // forward referenced goto's go here
ForeachStatement(Loc loc, TOK op, Parameters *arguments, Expression *aggr, Statement *body);
Statement *syntaxCopy();
@@ -455,7 +456,6 @@ public:
void toIR(IRState *irs);
};
#if DMDV2
class ForeachRangeStatement : public Statement
{
public:
@@ -483,7 +483,6 @@ public:
void toIR(IRState *irs);
};
#endif
class IfStatement : public Statement
{
@@ -631,7 +630,6 @@ public:
#endif
};
#if DMDV2
class CaseRangeStatement : public Statement
{
@@ -647,7 +645,6 @@ public:
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
class DefaultStatement : public Statement
{
@@ -961,16 +958,19 @@ class GotoStatement : public Statement
public:
Identifier *ident;
LabelDsymbol *label;
#if !IN_LLVM
TryFinallyStatement *tf;
#else
#if IN_LLVM
TryFinallyStatement *enclosingFinally;
Statement* enclosingScopeExit;
#else
TryFinallyStatement *tf;
#endif
VarDeclaration *lastVar;
FuncDeclaration *fd;
GotoStatement(Loc loc, Identifier *ident);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
bool checkLabel();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
void ctfeCompile(CompiledCtfeFunction *ccf);
@@ -991,6 +991,7 @@ public:
Statement* enclosingScopeExit;
#endif
Statement *gotoTarget; // interpret
VarDeclaration *lastVar;
block *lblock; // back end
Blocks *fwdrefs; // forward references to this LabelStatement
+2 -2
View File
@@ -77,7 +77,7 @@ void StaticAssert::semantic2(Scope *sc)
{
errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
}
else if (e->isBool(FALSE))
else if (e->isBool(false))
{
if (msg)
{
@@ -105,7 +105,7 @@ void StaticAssert::semantic2(Scope *sc)
if (!global.gag)
fatal();
}
else if (!e->isBool(TRUE))
else if (!e->isBool(true))
{
error("(%s) is not evaluatable at compile time", exp->toChars());
}
+1 -77
View File
@@ -120,12 +120,10 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
enclosing = NULL;
vthis = NULL;
#if DMDV2
ctor = NULL;
defaultCtor = NULL;
aliasthis = NULL;
noDefaultCtor = FALSE;
#endif
noDefaultCtor = false;
dtor = NULL;
getRTInfo = NULL;
@@ -565,7 +563,6 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
: AggregateDeclaration(loc, id)
{
zeroInit = 0; // assume false until we do semantic processing
#if DMDV2
hasIdentityAssign = 0;
hasIdentityEquals = 0;
cpctor = NULL;
@@ -574,7 +571,6 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
xeq = NULL;
xcmp = NULL;
alignment = 0;
#endif
arg1type = NULL;
arg2type = NULL;
@@ -582,16 +578,8 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
type = new TypeStruct(this);
#if MODULEINFO_IS_STRUCT
#ifdef DMDV2
if (id == Id::ModuleInfo && !Module::moduleinfo)
Module::moduleinfo = this;
#else
if (id == Id::ModuleInfo)
{ if (Module::moduleinfo)
Module::moduleinfo->error("only object.d can define this reserved struct name");
Module::moduleinfo = this;
}
#endif
#endif
}
@@ -758,69 +746,6 @@ void StructDeclaration::semantic(Scope *sc)
}
}
#if DMDV1
/* This doesn't work for DMDV2 because (ref S) and (S) parameter
* lists will overload the same.
*/
/* The TypeInfo_Struct is expecting an opEquals and opCmp with
* a parameter that is a pointer to the struct. But if there
* isn't one, but is an opEquals or opCmp with a value, write
* another that is a shell around the value:
* int opCmp(struct *p) { return opCmp(*p); }
*/
TypeFunction *tfeqptr;
{
Parameters *arguments = new Parameters;
Parameter *arg = new Parameter(STCin, handle, Id::p, NULL);
arguments->push(arg);
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), sc);
}
TypeFunction *tfeq;
{
Parameters *arguments = new Parameters;
Parameter *arg = new Parameter(STCin, type, NULL, NULL);
arguments->push(arg);
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeq = (TypeFunction *)tfeq->semantic(Loc(), sc);
}
Identifier *id = Id::eq;
for (int i = 0; i < 2; i++)
{
Dsymbol *s = search_function(this, id);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{ FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
if (!fd)
{ fd = fdx->overloadExactMatch(tfeq);
if (fd)
{ // Create the thunk, fdptr
FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
Expression *e = new IdentifierExp(loc, Id::p);
e = new PtrExp(loc, e);
Expressions *args = new Expressions();
args->push(e);
e = new IdentifierExp(loc, id);
e = new CallExp(loc, e, args);
fdptr->fbody = new ReturnStatement(loc, e);
ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
assert(s);
s->members->push(fdptr);
fdptr->addMember(sc, s, 1);
fdptr->semantic(sc2);
}
}
}
id = Id::cmp;
}
#endif
#if DMDV2
dtor = buildDtor(sc2);
postblit = buildPostBlit(sc2);
cpctor = buildCpCtor(sc2);
@@ -840,7 +765,6 @@ void StructDeclaration::semantic(Scope *sc)
/* Defer requesting semantic3 until TypeInfo generation is actually invoked.
* See Type::getTypeInfo().
*/
#endif
inv = buildInv(sc2);
sc2->pop();
+250 -130
View File
@@ -454,7 +454,6 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, RootObject *oarg)
}
}
#if DMDV2
RootObject *objectSyntaxCopy(RootObject *o)
{
if (!o)
@@ -467,13 +466,12 @@ RootObject *objectSyntaxCopy(RootObject *o)
return e->syntaxCopy();
return o;
}
#endif
/* ======================== TemplateDeclaration ============================= */
TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs, int ismixin)
TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs, bool ismixin, bool literal)
: ScopeDsymbol(id)
{
#if LOG
@@ -501,8 +499,9 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->overroot = NULL;
this->funcroot = NULL;
this->onemember = NULL;
this->literal = 0;
this->literal = literal;
this->ismixin = ismixin;
this->isstatic = true;
this->previous = NULL;
this->protection = PROTundefined;
this->numinstances = 0;
@@ -540,8 +539,7 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
if (constraint)
e = constraint->syntaxCopy();
Dsymbols *d = Dsymbol::arraySyntaxCopy(members);
td = new TemplateDeclaration(loc, ident, p, e, d, ismixin);
td->literal = literal;
td = new TemplateDeclaration(loc, ident, p, e, d, ismixin, literal);
#if IN_LLVM
td->intrinsicName = intrinsicName;
#endif
@@ -568,13 +566,6 @@ void TemplateDeclaration::semantic(Scope *sc)
Type::rtinfo = this;
}
if (sc->func)
{
#if DMDV1
error("cannot declare template at function scope %s", sc->func->toChars());
#endif
}
if (/*global.params.useArrayBounds &&*/ sc->module)
{
// Generate this function as it may be used
@@ -591,7 +582,6 @@ void TemplateDeclaration::semantic(Scope *sc)
//sc->module->toModuleAssert();
}
#if DMDV2
if (sc->module)
{
// Generate this function as it may be used
@@ -599,13 +589,13 @@ void TemplateDeclaration::semantic(Scope *sc)
// FIXME: LDC
// sc->module->toModuleUnittest();
}
#endif
/* Remember Scope for later instantiations, but make
* a copy since attributes can change.
*/
if (!this->scope)
{ this->scope = new Scope(*sc);
{
this->scope = new Scope(*sc);
this->scope->setNoFree();
}
@@ -618,6 +608,9 @@ void TemplateDeclaration::semantic(Scope *sc)
if (!parent)
parent = sc->parent;
isstatic = toParent()->isModule() ||
toParent()->isFuncDeclaration() && (scope->stc & STCstatic);
protection = sc->protection;
if (global.params.doDocComments)
@@ -644,7 +637,8 @@ void TemplateDeclaration::semantic(Scope *sc)
tp->semantic(paramscope, parameters);
if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
{ error("template tuple parameter must be last one");
{
error("template tuple parameter must be last one");
errors = true;
}
}
@@ -904,7 +898,6 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
}
}
#if DMDV2
if (m && constraint && !flag)
{
/* Check to see if constraint is satisfied.
@@ -979,16 +972,15 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
goto Lnomatch;
e = e->ctfeInterpret();
if (e->isBool(TRUE))
if (e->isBool(true))
;
else if (e->isBool(FALSE))
else if (e->isBool(false))
goto Lnomatch;
else
{
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
}
}
#endif
#if LOGM
// Print out the results
@@ -1135,8 +1127,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
unsigned wildmatch = 0;
TemplateParameters *inferparams = parameters;
TypeFunction *tf = (TypeFunction *)fd->type;
#if 0
printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
for (size_t i = 0; i < (fargs ? fargs->dim : 0); i++)
@@ -1157,7 +1147,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
dedtypes.setDim(parameters->dim);
dedtypes.zero();
if (errors)
if (errors || f->errors)
return MATCHnomatch;
// Set up scope for parameters
@@ -1222,11 +1212,10 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
for (size_t i = 0; i < n; i++)
{ assert(i < parameters->dim);
TemplateParameter *tp = (*parameters)[i];
MATCH m;
Declaration *sparam = NULL;
m = tp->matchArg(loc, paramscope, dedargs, i, parameters, &dedtypes, &sparam);
m = (*parameters)[i]->matchArg(loc, paramscope, dedargs, i, parameters, &dedtypes, &sparam);
//printf("\tdeduceType m = %d\n", m);
if (m == MATCHnomatch)
goto Lnomatch;
@@ -1312,15 +1301,14 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
}
}
#if DMDV2
if (tthis)
{
bool hasttp = false;
// Match 'tthis' to any TemplateThisParameter's
for (size_t i = 0; i < parameters->dim; i++)
{ TemplateParameter *tp = (*parameters)[i];
TemplateThisParameter *ttp = tp->isTemplateThisParameter();
{
TemplateThisParameter *ttp = (*parameters)[i]->isTemplateThisParameter();
if (ttp)
{ hasttp = true;
@@ -1336,7 +1324,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
// Match attributes of tthis against attributes of fd
if (fd->type && !fd->isCtorDeclaration())
{
unsigned mod = fd->type->mod;
unsigned char mod = fd->type->mod;
StorageClass stc = scope->stc | fd->storage_class2;
// Propagate parent storage class (see bug 5504)
Dsymbol *p = parent;
@@ -1360,7 +1348,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
if (mod & MODconst)
mod &= ~STCwild;
unsigned thismod = tthis->mod;
unsigned char thismod = tthis->mod;
if (hasttp)
mod = MODmerge(thismod, mod);
if (thismod != mod)
@@ -1372,7 +1360,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
}
}
}
#endif
// Loop through the function parameters
{
@@ -1667,7 +1654,6 @@ Lretry:
#endif
Type *argtype = farg->type;
#if DMDV2
/* Allow expressions that have CT-known boundaries and type [] to match with [dim]
*/
Type *taai;
@@ -1699,8 +1685,7 @@ Lretry:
*/
if (farg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)farg;
Type *tp = prmtype;
Expression *e = fe->inferType(tp, 1, paramscope, inferparams);
Expression *e = fe->inferType(prmtype, 1, paramscope, inferparams);
if (!e)
goto Lvarargs;
farg = e;
@@ -1719,7 +1704,6 @@ Lretry:
{
argtype = argtype->mutableOf();
}
#endif
if (fvarargs == 2 && parami + 1 == nfparams && argi + 1 < nfargs)
goto Lvarargs;
@@ -1741,7 +1725,6 @@ Lretry:
if (!m)
{ Type *tbp = prmtype->toBasetype();
Type *tba = farg->type->toBasetype();
AggregateDeclaration *ad;
if (tbp->ty == Tdelegate)
{
TypeDelegate *td = (TypeDelegate *)prmtype->toBasetype();
@@ -1755,23 +1738,18 @@ Lretry:
}
//printf("\tm2 = %d\n", m);
}
else if (tba->ty == Tclass)
else if (AggregateDeclaration *ad = isAggregate(tba))
{
ad = ((TypeClass *)tba)->sym;
goto Lad;
}
else if (tba->ty == Tstruct)
{
ad = ((TypeStruct *)tba)->sym;
Lad:
if (ad->aliasthis)
{ /* If a semantic error occurs while doing alias this,
{
/* If a semantic error occurs while doing alias this,
* eg purity(bug 7295), just regard it as not a match.
*/
unsigned olderrors = global.startGagging();
Expression *e = resolveAliasThis(sc, farg);
if (!global.endGagging(olderrors))
{ farg = e;
{
farg = e;
goto Lretry;
}
}
@@ -1881,9 +1859,8 @@ Lretry:
if (arg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)arg;
Type *tp = tb->nextOf();
Expression *e = fe->inferType(tp, 1, paramscope, inferparams);
Expression *e = fe->inferType(tb->nextOf(), 1, paramscope, inferparams);
if (!e)
goto Lnomatch;
arg = e;
@@ -1992,7 +1969,6 @@ Lmatch:
}
}
#if DMDV2
if (constraint)
{
/* Check to see if constraint is satisfied.
@@ -2037,7 +2013,6 @@ Lmatch:
int nerrors = global.errors;
FuncDeclaration *fd = f;
Dsymbol *s = parent;
while (s->isTemplateInstance() || s->isTemplateMixin())
s = s->parent;
@@ -2066,16 +2041,15 @@ Lmatch:
goto Lnomatch;
e = e->ctfeInterpret();
if (e->isBool(TRUE))
if (e->isBool(true))
;
else if (e->isBool(FALSE))
else if (e->isBool(false))
goto Lnomatch;
else
{
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
}
}
#endif
#if 0
for (i = 0; i < dedargs->dim; i++)
@@ -2251,10 +2225,13 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
static int fp(void *param, Dsymbol *s)
{
if (FuncDeclaration *fd = s->isFuncDeclaration())
return ((ParamDeduce *)param)->fp(fd);
if (TemplateDeclaration *td = s->isTemplateDeclaration())
return ((ParamDeduce *)param)->fp(td);
if (!s->errors)
{
if (FuncDeclaration *fd = s->isFuncDeclaration())
return ((ParamDeduce *)param)->fp(fd);
if (TemplateDeclaration *td = s->isTemplateDeclaration())
return ((ParamDeduce *)param)->fp(td);
}
return 0;
}
int fp(FuncDeclaration *fd)
@@ -2378,7 +2355,11 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
if (td->semanticRun == PASSinit)
{
::error(loc, "forward reference to template %s", td->toChars());
goto Lerror;
Lerror:
m->lastf = NULL;
m->count = 0;
m->last = MATCHnomatch;
return 1;
}
FuncDeclaration *f;
f = td->onemember ? td->onemember/*->toAlias()*/->isFuncDeclaration() : NULL;
@@ -2501,7 +2482,9 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
{
// Disambiguate by tf->callMatch
TypeFunction *tf1 = (TypeFunction *)fd->type;
assert(tf1->ty == Tfunction);
TypeFunction *tf2 = (TypeFunction *)m->lastf->type;
assert(tf2->ty == Tfunction);
MATCH c1 = tf1->callMatch(tthis_fd, fargs);
MATCH c2 = tf2->callMatch(tthis_best, fargs);
//printf("2: c1 = %d, c2 = %d\n", c1, c2);
@@ -2542,12 +2525,6 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
continue;
}
return 0;
Lerror:
m->lastf = NULL;
m->count = 0;
m->last = MATCHnomatch;
return 1;
}
};
ParamDeduce p;
@@ -2604,6 +2581,8 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
p.tthis_best = m->lastf->needThis() && !m->lastf->isCtorDeclaration() ? tthis : NULL;
TypeFunction *tf = (TypeFunction *)m->lastf->type;
if (tf->ty == Terror)
goto Lerror;
assert(tf->ty == Tfunction);
if (!tf->callMatch(p.tthis_best, fargs))
goto Lerror;
@@ -2719,15 +2698,15 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
sc2->tinst = ti;
{
Scope *sc = sc2;
sc = sc->push();
Scope *scx = sc2;
scx = scx->push();
if (hasttp)
fd->type = fd->type->addMod(tthis->mod);
//printf("tthis = %s, fdtype = %s\n", tthis->toChars(), fd->type->toChars());
if (fd->isCtorDeclaration())
{
sc->flags |= SCOPEctor;
scx->flags |= SCOPEctor;
Dsymbol *parent = toParent2();
Type *tret;
@@ -2739,7 +2718,7 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
else
{ tret = ad->handle;
assert(tret);
tret = tret->addStorageClass(fd->storage_class | sc->stc);
tret = tret->addStorageClass(fd->storage_class | scx->stc);
tret = tret->addMod(fd->type->mod);
}
((TypeFunction *)fd->type)->next = tret;
@@ -2747,9 +2726,9 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
((TypeFunction *)fd->type)->isref = 1;
//printf("fd->type = %s\n", fd->type->toChars());
}
fd->type = fd->type->addSTC(sc->stc);
fd->type = fd->type->semantic(fd->loc, sc);
sc = sc->pop();
fd->type = fd->type->addSTC(scx->stc);
fd->type = fd->type->semantic(fd->loc, scx);
scx = scx->pop();
}
//printf("\t[%s] fd->type = %s, mod = %x, ", loc.toChars(), fd->type->toChars(), fd->type->mod);
//printf("fd->needThis() = %d\n", fd->needThis());
@@ -2757,12 +2736,12 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
sc2->pop();
scope->pop();
return fd;
return fd->type->ty == Tfunction ? fd : NULL;
}
bool TemplateDeclaration::hasStaticCtorOrDtor()
{
return FALSE; // don't scan uninstantiated templates
return false; // don't scan uninstantiated templates
}
void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -2771,6 +2750,88 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (onemember && onemember->isFuncDeclaration())
buf->writestring("foo ");
#endif
if (hgs->hdrgen && members && members->dim == 1)
{
FuncDeclaration *fd = (*members)[0]->isFuncDeclaration();
if (fd && fd->type && fd->type->ty == Tfunction && fd->ident == ident)
{
TypeFunction *tf = (TypeFunction *)fd->type;
tf->toCBufferWithAttributes(buf, ident, hgs, tf, this);
if (constraint)
{
buf->writestring(" if (");
constraint->toCBuffer(buf, hgs);
buf->writeByte(')');
}
hgs->tpltMember++;
fd->bodyToCBuffer(buf, hgs);
hgs->tpltMember--;
return;
}
AggregateDeclaration *ad = (*members)[0]->isAggregateDeclaration();
if (ad)
{
buf->writestring(ad->kind());
buf->writeByte(' ');
buf->writestring(ident->toChars());
buf->writeByte('(');
for (size_t i = 0; i < parameters->dim; i++)
{
TemplateParameter *tp = (*parameters)[i];
if (hgs->ddoc)
tp = (*origParameters)[i];
if (i)
buf->writestring(", ");
tp->toCBuffer(buf, hgs);
}
buf->writeByte(')');
if (constraint)
{
buf->writestring(" if (");
constraint->toCBuffer(buf, hgs);
buf->writeByte(')');
}
ClassDeclaration *cd = ad->isClassDeclaration();
if (cd && cd->baseclasses->dim)
{
buf->writestring(" : ");
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{
BaseClass *b = (*cd->baseclasses)[i];
if (i)
buf->writestring(", ");
b->type->toCBuffer(buf, NULL, hgs);
}
}
hgs->tpltMember++;
if (ad->members)
{
buf->writenl();
buf->writeByte('{');
buf->writenl();
buf->level++;
for (size_t i = 0; i < ad->members->dim; i++)
{
Dsymbol *s = (*ad->members)[i];
s->toCBuffer(buf, hgs);
}
buf->level--;
buf->writestring("}");
}
else
buf->writeByte(';');
buf->writenl();
hgs->tpltMember--;
return;
}
}
if (hgs->ddoc)
buf->writestring(kind());
else
@@ -2788,13 +2849,12 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
tp->toCBuffer(buf, hgs);
}
buf->writeByte(')');
#if DMDV2
if (constraint)
{ buf->writestring(" if (");
{
buf->writestring(" if (");
constraint->toCBuffer(buf, hgs);
buf->writeByte(')');
}
#endif
if (hgs->hdrgen)
{
@@ -2817,7 +2877,11 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
char *TemplateDeclaration::toChars()
{ OutBuffer buf;
{
if (literal)
return Dsymbol::toChars();
OutBuffer buf;
HdrGenState hgs;
memset(&hgs, 0, sizeof(hgs));
@@ -2833,7 +2897,8 @@ char *TemplateDeclaration::toChars()
buf.writeByte(')');
if (onemember)
{ /* Bugzilla 9406:
{
/* Bugzilla 9406:
* onemember->toAlias() might run semantic, so should not call it in stringizing
*/
FuncDeclaration *fd = onemember->isFuncDeclaration();
@@ -2845,13 +2910,12 @@ char *TemplateDeclaration::toChars()
}
}
#if DMDV2
if (constraint)
{ buf.writestring(" if (");
{
buf.writestring(" if (");
constraint->toCBuffer(&buf, &hgs);
buf.writeByte(')');
}
#endif
buf.writeByte(0);
return (char *)buf.extractData();
}
@@ -3348,7 +3412,12 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
if (ty != tparam->ty)
{
#if DMDV2
if (Dsymbol *sym = toDsymbol(sc))
{
if (sym->isforwardRef() && !tparam->deco)
goto Lnomatch;
}
// Can't instantiate AssociativeArray!() without a scope
if (tparam->ty == Taarray && !((TypeAArray*)tparam)->sc)
((TypeAArray*)tparam)->sc = sc;
@@ -3361,9 +3430,6 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
m = at->deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
return m;
#else
return implicitConvTo(tparam);
#endif
}
if (nextOf())
@@ -3380,13 +3446,10 @@ Lexact:
Lnomatch:
return MATCHnomatch;
#if DMDV2
Lconst:
return MATCHconst;
#endif
}
#if DMDV2
MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes, unsigned *wildmatch)
{
@@ -3401,9 +3464,7 @@ MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
}
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
#endif
#if DMDV2
MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes, unsigned *wildmatch)
{
@@ -3414,7 +3475,6 @@ MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
#endif
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
#endif
MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes, unsigned *wildmatch)
@@ -3628,12 +3688,12 @@ MATCH TypeInstance::deduceType(Scope *sc,
printf("\tthis = %d, ", ty); print();
printf("\ttparam = %d, ", tparam->ty); tparam->print();
#endif
TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration();
assert(tempdecl);
// Extra check
if (tparam && tparam->ty == Tinstance)
if (tparam && tparam->ty == Tinstance && tempinst->tempdecl)
{
TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration();
assert(tempdecl);
TypeInstance *tp = (TypeInstance *)tparam;
//printf("tempinst->tempdecl = %p\n", tempdecl);
@@ -3816,8 +3876,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
goto Le;
goto Lnomatch;
}
TemplateParameter *tp = (*parameters)[j];
if (!tp->matchArg(sc, e1, j, parameters, dedtypes, NULL))
if (!(*parameters)[j]->matchArg(sc, e1, j, parameters, dedtypes, NULL))
goto Lnomatch;
}
else if (s1 && s2)
@@ -3836,8 +3895,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
goto Ls;
goto Lnomatch;
}
TemplateParameter *tp = (*parameters)[j];
if (!tp->matchArg(sc, s1, j, parameters, dedtypes, NULL))
if (!(*parameters)[j]->matchArg(sc, s1, j, parameters, dedtypes, NULL))
goto Lnomatch;
}
else
@@ -3899,6 +3957,8 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
TypeStruct *tp = (TypeStruct *)tparam;
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
if (wildmatch && wildConvTo(tparam))
return MATCHconst;
return implicitConvTo(tp);
}
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
@@ -4084,6 +4144,8 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
TypeClass *tp = (TypeClass *)tparam;
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
if (wildmatch && wildConvTo(tparam))
return MATCHconst;
return implicitConvTo(tp);
}
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
@@ -4118,12 +4180,10 @@ TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter()
return NULL;
}
#if DMDV2
TemplateThisParameter *TemplateParameter::isTemplateThisParameter()
{
return NULL;
}
#endif
/*******************************************
* Match to a particular TemplateParameter.
@@ -4343,12 +4403,13 @@ void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
void *TemplateTypeParameter::dummyArg()
{ Type *t;
{
Type *t;
if (specType)
t = specType;
else
{ // Use this for alias-parameter's too (?)
{
// Use this for alias-parameter's too (?)
if (!tdummy)
tdummy = new TypeIdentifier(loc, ident);
t = tdummy;
@@ -4378,7 +4439,6 @@ RootObject *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
/* ======================== TemplateThisParameter =========================== */
#if DMDV2
// this-parameter
TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident,
@@ -4408,7 +4468,6 @@ void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("this ");
TemplateTypeParameter::toCBuffer(buf, hgs);
}
#endif
/* ======================== TemplateAliasParameter ========================== */
@@ -4982,9 +5041,7 @@ RootObject *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
e = e->syntaxCopy();
e = e->semantic(sc);
e = resolveProperties(sc, e);
#if DMDV2
e = e->resolveLoc(loc, sc);
#endif
}
return e;
}
@@ -5151,6 +5208,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->instantiatingModule = NULL;
this->inst = NULL;
this->tinst = NULL;
this->deferred = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semantictiargsdone = false;
@@ -5185,6 +5243,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->instantiatingModule = NULL;
this->inst = NULL;
this->tinst = NULL;
this->deferred = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semantictiargsdone = true;
@@ -5246,9 +5305,11 @@ void TemplateInstance::semantic(Scope *sc)
void TemplateInstance::expandMembers(Scope *sc2)
{
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
{
Dsymbol *s = (*members)[i];
s->setScope(sc2);
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
@@ -5402,7 +5463,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
if (tempdecl->ismixin)
error("mixin templates are not regular templates");
hasNestedArgs(tiargs);
hasNestedArgs(tiargs, tempdecl->isstatic);
arrayCheckRecursiveExpansion(&tdtypes, tempdecl, sc);
@@ -5521,10 +5582,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
Module *m = (Module *)s;
if (!m->isRoot())
{
//if (tinst && tinst->objFileModule)
// m = tinst->objFileModule;
//else
m = m->importedFrom;
m = m->importedFrom;
}
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
a = m->members;
@@ -5551,7 +5609,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
#endif
// Copy the syntax trees from the TemplateDeclaration
if (members && speculative)
if (members && speculative && !errors)
{} // Don't copy again so they were previously created.
else
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
@@ -5680,6 +5738,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
sc2->parent = /*enclosing ? sc->parent :*/ this;
sc2->tinst = this;
sc2->speculative = speculative;
if (enclosing && tempdecl->isstatic)
sc2->stc &= ~STCstatic;
tryExpandMembers(sc2);
@@ -5743,10 +5803,64 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
semantic2(sc2);
}
if (sc->func)
if (sc->func && aliasdecl && aliasdecl->toAlias()->isFuncDeclaration())
{
/* Template function instantiation should run semantic3 immediately
* for attribute inference.
*/
//printf("function semantic3 %s inside %s\n", toChars(), sc->func->toChars());
trySemantic3(sc2);
}
else if (sc->func && !tinst)
{
/* If a template is instantiated inside function, the whole instantiation
* should be done at that position. But, immediate running semantic3 of
* dependent templates may cause unresolved forward reference (Bugzilla 9050).
* To avoid the issue, don't run semantic3 until semantic and semantic2 done.
*/
TemplateInstances deferred;
this->deferred = &deferred;
//printf("Run semantic3 on %s\n", toChars());
trySemantic3(sc2);
for (size_t i = 0; i < deferred.dim; i++)
{
//printf("+ run deferred semantic3 on %s\n", deferred[i]->toChars());
deferred[i]->semantic3(NULL);
}
this->deferred = NULL;
}
else if (tinst)
{
TemplateInstance *ti = tinst;
int nest = 0;
while (ti && !ti->deferred && ti->tinst)
{
ti = ti->tinst;
if (++nest > 500)
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
}
if (ti && ti->deferred)
{
//printf("deferred semantic3 of %p %s, ti = %s, ti->deferred = %p\n", this, toChars(), ti->toChars());
for (size_t i = 0; ; i++)
{
if (i == ti->deferred->dim)
{
ti->deferred->push(this);
break;
}
if ((*ti->deferred)[i] == this)
break;
}
}
}
Laftersemantic:
sc2->pop();
@@ -5756,7 +5870,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
// Give additional context info if error occurred during instantiation
if (global.errors != errorsave)
{
error(loc, "error instantiating");
if (!tempdecl->literal)
error(loc, "error instantiating");
if (tinst)
{ tinst->printInstantiationTrace();
}
@@ -6571,7 +6686,7 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag)
* Sets enclosing property if so, and returns != 0;
*/
bool TemplateInstance::hasNestedArgs(Objects *args)
bool TemplateInstance::hasNestedArgs(Objects *args, bool isstatic)
{
int nested = 0;
//printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars());
@@ -6656,15 +6771,13 @@ bool TemplateInstance::hasNestedArgs(Objects *args)
(ad && ad->isNested()) ||
#endif
(d && !d->isDataseg() &&
#if DMDV2
!(d->storage_class & STCmanifest) &&
#endif
(!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
!isTemplateMixin()
))
{
// if module level template
if (tempdecl->toParent()->isModule())
if (isstatic)
{
Dsymbol *dparent = sa->toParent2();
if (!enclosing)
@@ -6699,7 +6812,7 @@ bool TemplateInstance::hasNestedArgs(Objects *args)
}
else if (va)
{
nested |= hasNestedArgs(&va->objects);
nested |= hasNestedArgs(&va->objects, isstatic);
}
}
//printf("-TemplateInstance::hasNestedArgs('%s') = %d\n", tempdecl->ident->toChars(), nested);
@@ -7058,6 +7171,8 @@ void TemplateInstance::toCBufferTiargs(OutBuffer *buf, HdrGenState *hgs)
buf->writeByte('!');
if (nest)
buf->writestring("(...)");
else if (!tiargs)
buf->writestring("()");
else
{
if (tiargs->dim == 1)
@@ -7192,7 +7307,7 @@ int TemplateInstance::compare(RootObject *o)
if (fargs)
{
FuncDeclaration *fd = ti->toAlias()->isFuncDeclaration();
if (fd)
if (fd && !fd->errors)
{
Parameters *fparameters = fd->getParameters(NULL);
size_t nfparams = Parameter::dim(fparameters); // Num function parameters
@@ -7200,8 +7315,6 @@ int TemplateInstance::compare(RootObject *o)
{
Parameter *fparam = Parameter::getNth(fparameters, j);
Expression *farg = (*fargs)[j];
if (Expression *e = farg->isTemp())
farg = e;
if (fparam->storageClass & STCauto) // if "auto ref"
{
if (farg->isLvalue())
@@ -7278,18 +7391,18 @@ bool TemplateMixin::findTemplateDeclaration(Scope *sc)
*/
if (os)
{
Dsymbol *s = NULL;
Dsymbol *ds = NULL;
for (size_t i = 0; i < os->a.dim; i++)
{
Dsymbol *s2 = os->a[i]->isTemplateDeclaration();
if (s2)
{
if (s)
if (ds)
{
tempdecl = os;
break;
}
s = s2;
ds = s2;
}
}
}
@@ -7467,7 +7580,7 @@ void TemplateMixin::semantic(Scope *sc)
}
// Copy the syntax trees from the TemplateDeclaration
if (scx && members)
if (scx && members && !errors)
{} // Don't copy again so they were previously created.
else
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
@@ -7529,6 +7642,12 @@ void TemplateMixin::semantic(Scope *sc)
fatal();
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
s->setScope(sc2);
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
@@ -7580,6 +7699,7 @@ void TemplateMixin::semantic(Scope *sc)
if (global.errors != errorsave)
{
error("error instantiating");
errors = true;
}
sc2->pop();
+7 -14
View File
@@ -71,8 +71,9 @@ public:
Dsymbol *onemember; // if !=NULL then one member of this template
int literal; // this template declaration is a literal
int ismixin; // template declaration is only to be used as a mixin
bool literal; // this template declaration is a literal
bool ismixin; // template declaration is only to be used as a mixin
bool isstatic; // this is static template declaration
PROT protection;
struct Previous
@@ -83,7 +84,7 @@ public:
Previous *previous; // threaded list of previous instantiation attempts on stack
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
Expression *constraint, Dsymbols *decldefs, int ismixin);
Expression *constraint, Dsymbols *decldefs, bool ismixin = false, bool literal = false);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
bool overloadInsert(Dsymbol *s);
@@ -145,9 +146,7 @@ public:
virtual TemplateTypeParameter *isTemplateTypeParameter();
virtual TemplateValueParameter *isTemplateValueParameter();
virtual TemplateAliasParameter *isTemplateAliasParameter();
#if DMDV2
virtual TemplateThisParameter *isTemplateThisParameter();
#endif
virtual TemplateTupleParameter *isTemplateTupleParameter();
virtual TemplateParameter *syntaxCopy() = 0;
@@ -198,7 +197,6 @@ public:
void *dummyArg();
};
#if DMDV2
class TemplateThisParameter : public TemplateTypeParameter
{
public:
@@ -212,7 +210,6 @@ public:
TemplateParameter *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
class TemplateValueParameter : public TemplateParameter
{
@@ -324,12 +321,8 @@ public:
hash_t hash; // cached result of hashCode()
Expressions *fargs; // for function template, these are the function arguments
Module *instantiatingModule; // the top module that instantiated this instance
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
will be emitted in the output or not before the symbol
is used. This can be different from getModule(). */
Module * objFileModule;
#endif
TemplateInstances* deferred;
TemplateInstance(Loc loc, Identifier *temp_id);
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
@@ -363,7 +356,7 @@ public:
bool semanticTiargs(Scope *sc);
bool findBestMatch(Scope *sc, Expressions *fargs);
bool needsTypeInference(Scope *sc, int flag = 0);
bool hasNestedArgs(Objects *tiargs);
bool hasNestedArgs(Objects *tiargs, bool isstatic);
void declareParameters(Scope *sc);
Identifier *genIdent(Objects *args);
void expandMembers(Scope *sc);
+102 -67
View File
@@ -38,7 +38,6 @@
#define LOGSEMANTIC 0
#if DMDV2
/************************************************
* Delegate to be passed to overloadApply() that looks
@@ -93,6 +92,8 @@ static int fptraits(void *param, Dsymbol *s)
*/
static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions *unitTests)
{
if (!symbols)
return;
for (size_t i = 0; i < symbols->dim; i++)
{
Dsymbol *symbol = (*symbols)[i];
@@ -124,6 +125,81 @@ static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions
/************************ TraitsExp ************************************/
bool isTypeArithmetic(Type *t) { return t->isintegral() || t->isfloating(); }
bool isTypeFloating(Type *t) { return t->isfloating(); }
bool isTypeIntegral(Type *t) { return t->isintegral(); }
bool isTypeScalar(Type *t) { return t->isscalar(); }
bool isTypeUnsigned(Type *t) { return t->isunsigned(); }
bool isTypeAssociativeArray(Type *t) { return t->toBasetype()->ty == Taarray; }
bool isTypeStaticArray(Type *t) { return t->toBasetype()->ty == Tsarray; }
bool isTypeAbstractClass(Type *t) { return t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract(); }
bool isTypeFinalClass(Type *t) { return t->toBasetype()->ty == Tclass && (((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal) != 0; }
Expression *TraitsExp::isTypeX(bool (*fp)(Type *t))
{
int result = 0;
if (!args || !args->dim)
goto Lfalse;
for (size_t i = 0; i < args->dim; i++)
{
Type *t = getType((*args)[i]);
if (!t || !fp(t))
goto Lfalse;
}
result = 1;
Lfalse:
return new IntegerExp(loc, result, Type::tbool);
}
bool isFuncAbstractFunction(FuncDeclaration *f) { return f->isAbstract(); }
bool isFuncVirtualFunction(FuncDeclaration *f) { return f->isVirtual(); }
bool isFuncVirtualMethod(FuncDeclaration *f) { return f->isVirtualMethod(); }
bool isFuncFinalFunction(FuncDeclaration *f) { return f->isFinalFunc(); }
bool isFuncStaticFunction(FuncDeclaration *f) { return !f->needThis() && !f->isNested(); }
bool isFuncOverrideFunction(FuncDeclaration *f) { return f->isOverride(); }
Expression *TraitsExp::isFuncX(bool (*fp)(FuncDeclaration *f))
{
int result = 0;
if (!args || !args->dim)
goto Lfalse;
for (size_t i = 0; i < args->dim; i++)
{
Dsymbol *s = getDsymbol((*args)[i]);
if (!s)
goto Lfalse;
FuncDeclaration *f = s->isFuncDeclaration();
if (!f || !fp(f))
goto Lfalse;
}
result = 1;
Lfalse:
return new IntegerExp(loc, result, Type::tbool);
}
bool isDeclRef(Declaration *d) { return d->isRef(); }
bool isDeclOut(Declaration *d) { return d->isOut(); }
bool isDeclLazy(Declaration *d) { return (d->storage_class & STClazy) != 0; }
Expression *TraitsExp::isDeclX(bool (*fp)(Declaration *d))
{
int result = 0;
if (!args || !args->dim)
goto Lfalse;
for (size_t i = 0; i < args->dim; i++)
{
Dsymbol *s = getDsymbol((*args)[i]);
if (!s)
goto Lfalse;
Declaration *d = s->isDeclaration();
if (!d || !fp(d))
goto Lfalse;
}
result = 1;
Lfalse:
return new IntegerExp(loc, result, Type::tbool);
}
Expression *TraitsExp::semantic(Scope *sc)
{
#if LOGSEMANTIC
@@ -137,67 +213,41 @@ Expression *TraitsExp::semantic(Scope *sc)
size_t dim = args ? args->dim : 0;
Declaration *d;
#define ISTYPE(cond) \
for (size_t i = 0; i < dim; i++) \
{ Type *t = getType((*args)[i]); \
if (!t) \
goto Lfalse; \
if (!(cond)) \
goto Lfalse; \
} \
if (!dim) \
goto Lfalse; \
goto Ltrue;
#define ISDSYMBOL(cond) \
for (size_t i = 0; i < dim; i++) \
{ Dsymbol *s = getDsymbol((*args)[i]); \
if (!s) \
goto Lfalse; \
if (!(cond)) \
goto Lfalse; \
} \
if (!dim) \
goto Lfalse; \
goto Ltrue;
if (ident == Id::isArithmetic)
{
ISTYPE(t->isintegral() || t->isfloating())
return isTypeX(&isTypeArithmetic);
}
else if (ident == Id::isFloating)
{
ISTYPE(t->isfloating())
return isTypeX(&isTypeFloating);
}
else if (ident == Id::isIntegral)
{
ISTYPE(t->isintegral())
return isTypeX(&isTypeIntegral);
}
else if (ident == Id::isScalar)
{
ISTYPE(t->isscalar())
return isTypeX(&isTypeScalar);
}
else if (ident == Id::isUnsigned)
{
ISTYPE(t->isunsigned())
return isTypeX(&isTypeUnsigned);
}
else if (ident == Id::isAssociativeArray)
{
ISTYPE(t->toBasetype()->ty == Taarray)
return isTypeX(&isTypeAssociativeArray);
}
else if (ident == Id::isStaticArray)
{
ISTYPE(t->toBasetype()->ty == Tsarray)
return isTypeX(&isTypeStaticArray);
}
else if (ident == Id::isAbstractClass)
{
ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
return isTypeX(&isTypeAbstractClass);
}
else if (ident == Id::isFinalClass)
{
ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
return isTypeX(&isTypeFinalClass);
}
else if (ident == Id::isPOD)
{
@@ -251,41 +301,35 @@ Expression *TraitsExp::semantic(Scope *sc)
}
else if (ident == Id::isAbstractFunction)
{
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
return isFuncX(&isFuncAbstractFunction);
}
else if (ident == Id::isVirtualFunction)
{
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
return isFuncX(&isFuncVirtualFunction);
}
else if (ident == Id::isVirtualMethod)
{
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtualMethod())
return isFuncX(&isFuncVirtualMethod);
}
else if (ident == Id::isFinalFunction)
{
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinalFunc())
return isFuncX(&isFuncFinalFunction);
}
#if DMDV2
else if (ident == Id::isStaticFunction)
{
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis() && !f->isNested())
return isFuncX(&isFuncStaticFunction);
}
else if (ident == Id::isRef)
{
ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isRef())
return isDeclX(&isDeclRef);
}
else if (ident == Id::isOut)
{
ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isOut())
return isDeclX(&isDeclOut);
}
else if (ident == Id::isLazy)
{
ISDSYMBOL((d = s->isDeclaration()) != NULL && d->storage_class & STClazy)
return isDeclX(&isDeclLazy);
}
else if (ident == Id::identifier)
{ // Get identifier for symbol as a string literal
@@ -366,7 +410,6 @@ Expression *TraitsExp::semantic(Scope *sc)
}
return (new DsymbolExp(loc, s))->semantic(sc);
}
#endif
else if (ident == Id::hasMember ||
ident == Id::getMember ||
ident == Id::getOverloads ||
@@ -614,16 +657,11 @@ Expression *TraitsExp::semantic(Scope *sc)
(*exps)[i] = se;
}
#if DMDV1
Expression *e = new ArrayLiteralExp(loc, exps);
#endif
#if DMDV2
/* Making this a tuple is more flexible, as it can be statically unrolled.
* To make an array literal, enclose __traits in [ ]:
* [ __traits(allMembers, ...) ]
*/
Expression *e = new TupleExp(loc, exps);
#endif
e = e->semantic(sc);
return e;
}
@@ -640,9 +678,9 @@ Expression *TraitsExp::semantic(Scope *sc)
unsigned errors = global.startGagging();
unsigned oldspec = global.speculativeGag;
global.speculativeGag = global.gag;
sc = sc->push();
sc->speculative = true;
sc->flags = sc->enclosing->flags & ~SCOPEctfe; // inherit without CTFEing
Scope *sc2 = sc->push();
sc2->speculative = true;
sc2->flags = sc->flags & ~SCOPEctfe | SCOPEcompile;
bool err = false;
RootObject *o = (*args)[i];
@@ -651,10 +689,10 @@ Expression *TraitsExp::semantic(Scope *sc)
if (!e && t)
{
Dsymbol *s;
t->resolve(loc, sc, &e, &t, &s);
t->resolve(loc, sc2, &e, &t, &s);
if (t)
{
t->semantic(loc, sc);
t->semantic(loc, sc2);
if (t->ty == Terror)
err = true;
}
@@ -663,13 +701,13 @@ Expression *TraitsExp::semantic(Scope *sc)
}
if (e)
{
e = e->semantic(sc);
e = e->semantic(sc2);
e = e->optimize(WANTvalue);
if (e->op == TOKerror)
err = true;
}
sc = sc->pop();
sc2->pop();
global.speculativeGag = oldspec;
if (global.endGagging(errors) || err)
{
@@ -770,8 +808,7 @@ Expression *TraitsExp::semantic(Scope *sc)
}
else if (ident == Id::isOverrideFunction)
{
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isOverride())
return isFuncX(&isFuncOverrideFunction);
}
else if(ident == Id::getVirtualIndex)
{
@@ -807,5 +844,3 @@ Lfalse:
Ltrue:
return new IntegerExp(loc, 1, Type::tbool);
}
#endif