mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-25 23:00:20 +02:00
First import of dmd-2.065-b1 (7088593).
The CPP mangling is not integrated yet.
This commit is contained in:
@@ -57,7 +57,6 @@ public:
|
|||||||
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
|
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
|
||||||
bool isdeprecated; // !=0 if deprecated
|
bool isdeprecated; // !=0 if deprecated
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
Dsymbol *enclosing; /* !=NULL if is nested
|
Dsymbol *enclosing; /* !=NULL if is nested
|
||||||
* pointing to the dsymbol that directly enclosing it.
|
* pointing to the dsymbol that directly enclosing it.
|
||||||
* 1. The function that enclosing it (nested struct and class)
|
* 1. The function that enclosing it (nested struct and class)
|
||||||
@@ -66,20 +65,17 @@ public:
|
|||||||
* See AggregateDeclaraton::makeNested for the details.
|
* See AggregateDeclaraton::makeNested for the details.
|
||||||
*/
|
*/
|
||||||
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
|
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
|
||||||
#endif
|
|
||||||
// Special member functions
|
// Special member functions
|
||||||
FuncDeclarations invs; // Array of invariants
|
FuncDeclarations invs; // Array of invariants
|
||||||
FuncDeclaration *inv; // invariant
|
FuncDeclaration *inv; // invariant
|
||||||
NewDeclaration *aggNew; // allocator
|
NewDeclaration *aggNew; // allocator
|
||||||
DeleteDeclaration *aggDelete; // deallocator
|
DeleteDeclaration *aggDelete; // deallocator
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
|
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
|
||||||
CtorDeclaration *defaultCtor; // default constructor - should have no arguments, because
|
CtorDeclaration *defaultCtor; // default constructor - should have no arguments, because
|
||||||
// it would be stored in TypeInfo_Class.defaultConstructor
|
// it would be stored in TypeInfo_Class.defaultConstructor
|
||||||
Dsymbol *aliasthis; // forward unresolved lookups to aliasthis
|
Dsymbol *aliasthis; // forward unresolved lookups to aliasthis
|
||||||
bool noDefaultCtor; // no default construction
|
bool noDefaultCtor; // no default construction
|
||||||
#endif
|
|
||||||
|
|
||||||
FuncDeclarations dtors; // Array of destructors
|
FuncDeclarations dtors; // Array of destructors
|
||||||
FuncDeclaration *dtor; // aggregate destructor
|
FuncDeclaration *dtor; // aggregate destructor
|
||||||
@@ -152,7 +148,6 @@ class StructDeclaration : public AggregateDeclaration
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int zeroInit; // !=0 if initialize with 0 fill
|
int zeroInit; // !=0 if initialize with 0 fill
|
||||||
#if DMDV2
|
|
||||||
int hasIdentityAssign; // !=0 if has identity opAssign
|
int hasIdentityAssign; // !=0 if has identity opAssign
|
||||||
int hasIdentityEquals; // !=0 if has identity opEquals
|
int hasIdentityEquals; // !=0 if has identity opEquals
|
||||||
FuncDeclaration *cpctor; // generated copy-constructor, if any
|
FuncDeclaration *cpctor; // generated copy-constructor, if any
|
||||||
@@ -165,7 +160,6 @@ public:
|
|||||||
static FuncDeclaration *xerrcmp; // object.xopCmp
|
static FuncDeclaration *xerrcmp; // object.xopCmp
|
||||||
|
|
||||||
structalign_t alignment; // alignment applied outside of the struct
|
structalign_t alignment; // alignment applied outside of the struct
|
||||||
#endif
|
|
||||||
|
|
||||||
// For 64 bit Efl function call/return ABI
|
// For 64 bit Efl function call/return ABI
|
||||||
Type *arg1type;
|
Type *arg1type;
|
||||||
@@ -180,10 +174,6 @@ public:
|
|||||||
const char *kind();
|
const char *kind();
|
||||||
void finalizeSize(Scope *sc);
|
void finalizeSize(Scope *sc);
|
||||||
bool isPOD();
|
bool isPOD();
|
||||||
#if DMDV1
|
|
||||||
Expression *cloneMembers();
|
|
||||||
#endif
|
|
||||||
#if DMDV2
|
|
||||||
int needOpAssign();
|
int needOpAssign();
|
||||||
int needOpEquals();
|
int needOpEquals();
|
||||||
FuncDeclaration *buildOpAssign(Scope *sc);
|
FuncDeclaration *buildOpAssign(Scope *sc);
|
||||||
@@ -192,7 +182,6 @@ public:
|
|||||||
FuncDeclaration *buildOpEquals(Scope *sc);
|
FuncDeclaration *buildOpEquals(Scope *sc);
|
||||||
FuncDeclaration *buildXopEquals(Scope *sc);
|
FuncDeclaration *buildXopEquals(Scope *sc);
|
||||||
FuncDeclaration *buildXopCmp(Scope *sc);
|
FuncDeclaration *buildXopCmp(Scope *sc);
|
||||||
#endif
|
|
||||||
void toDocBuffer(OutBuffer *buf, Scope *sc);
|
void toDocBuffer(OutBuffer *buf, Scope *sc);
|
||||||
|
|
||||||
PROT getAccess(Dsymbol *smember); // determine access to smember
|
PROT getAccess(Dsymbol *smember); // determine access to smember
|
||||||
@@ -241,13 +230,8 @@ struct BaseClass
|
|||||||
void copyBaseInterfaces(BaseClasses *);
|
void copyBaseInterfaces(BaseClasses *);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
#define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size
|
#define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size
|
||||||
#define CLASSINFO_SIZE (0x3C+12+4) // 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
|
struct ClassFlags
|
||||||
{
|
{
|
||||||
@@ -274,10 +258,6 @@ public:
|
|||||||
static ClassDeclaration *errorException;
|
static ClassDeclaration *errorException;
|
||||||
|
|
||||||
ClassDeclaration *baseClass; // NULL only if this is Object
|
ClassDeclaration *baseClass; // NULL only if this is Object
|
||||||
#if DMDV1
|
|
||||||
CtorDeclaration *ctor;
|
|
||||||
CtorDeclaration *defaultCtor; // default constructor
|
|
||||||
#endif
|
|
||||||
FuncDeclaration *staticCtor;
|
FuncDeclaration *staticCtor;
|
||||||
FuncDeclaration *staticDtor;
|
FuncDeclaration *staticDtor;
|
||||||
Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[]
|
Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[]
|
||||||
@@ -296,9 +276,7 @@ public:
|
|||||||
TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
|
TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
|
||||||
int com; // !=0 if this is a COM class (meaning
|
int com; // !=0 if this is a COM class (meaning
|
||||||
// it derives from IUnknown)
|
// it derives from IUnknown)
|
||||||
#if DMDV2
|
|
||||||
int cpp; // !=0 if this is a C++ interface
|
int cpp; // !=0 if this is a C++ interface
|
||||||
#endif
|
|
||||||
int isscope; // !=0 if this is an auto class
|
int isscope; // !=0 if this is an auto class
|
||||||
int isabstract; // !=0 if abstract class
|
int isabstract; // !=0 if abstract class
|
||||||
int inuse; // to prevent recursive attempts
|
int inuse; // to prevent recursive attempts
|
||||||
@@ -318,17 +296,13 @@ public:
|
|||||||
virtual int isBaseInfoComplete();
|
virtual int isBaseInfoComplete();
|
||||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||||
ClassDeclaration *searchBase(Loc, Identifier *ident);
|
ClassDeclaration *searchBase(Loc, Identifier *ident);
|
||||||
#if DMDV2
|
|
||||||
int isFuncHidden(FuncDeclaration *fd);
|
int isFuncHidden(FuncDeclaration *fd);
|
||||||
#endif
|
|
||||||
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
|
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
|
||||||
void interfaceSemantic(Scope *sc);
|
void interfaceSemantic(Scope *sc);
|
||||||
int isCOMclass();
|
int isCOMclass();
|
||||||
virtual int isCOMinterface();
|
virtual int isCOMinterface();
|
||||||
#if DMDV2
|
|
||||||
int isCPPclass();
|
int isCPPclass();
|
||||||
virtual int isCPPinterface();
|
virtual int isCPPinterface();
|
||||||
#endif
|
|
||||||
bool isAbstract();
|
bool isAbstract();
|
||||||
virtual int vtblOffset();
|
virtual int vtblOffset();
|
||||||
const char *kind();
|
const char *kind();
|
||||||
@@ -370,9 +344,7 @@ public:
|
|||||||
const char *kind();
|
const char *kind();
|
||||||
int isBaseInfoComplete();
|
int isBaseInfoComplete();
|
||||||
int vtblOffset();
|
int vtblOffset();
|
||||||
#if DMDV2
|
|
||||||
int isCPPinterface();
|
int isCPPinterface();
|
||||||
#endif
|
|
||||||
virtual int isCOMinterface();
|
virtual int isCOMinterface();
|
||||||
|
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
|
|||||||
+33
-38
@@ -20,40 +20,30 @@
|
|||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
#include "declaration.h"
|
#include "declaration.h"
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
|
|
||||||
Expression *resolveAliasThis(Scope *sc, Expression *e)
|
Expression *resolveAliasThis(Scope *sc, Expression *e)
|
||||||
{
|
{
|
||||||
Type *t = e->type->toBasetype();
|
Type *t = e->type->toBasetype();
|
||||||
AggregateDeclaration *ad;
|
AggregateDeclaration *ad = isAggregate(t);
|
||||||
|
|
||||||
if (t->ty == Tclass)
|
if (ad && ad->aliasthis)
|
||||||
{ ad = ((TypeClass *)t)->sym;
|
{
|
||||||
goto L1;
|
bool isstatic = (e->op == TOKtype);
|
||||||
}
|
e = new DotIdExp(e->loc, e, ad->aliasthis->ident);
|
||||||
else if (t->ty == Tstruct)
|
e = e->semantic(sc);
|
||||||
{ ad = ((TypeStruct *)t)->sym;
|
if (isstatic && ad->aliasthis->needThis())
|
||||||
L1:
|
|
||||||
if (ad && ad->aliasthis)
|
|
||||||
{
|
{
|
||||||
bool isstatic = (e->op == TOKtype);
|
/* non-@property function is not called inside typeof(),
|
||||||
e = new DotIdExp(e->loc, e, ad->aliasthis->ident);
|
* so resolve it ahead.
|
||||||
e = e->semantic(sc);
|
*/
|
||||||
if (isstatic && ad->aliasthis->needThis())
|
int save = sc->intypeof;
|
||||||
{
|
sc->intypeof = 1; // bypass "need this" error check
|
||||||
/* 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);
|
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;
|
return e;
|
||||||
@@ -88,7 +78,8 @@ void AliasThis::semantic(Scope *sc)
|
|||||||
assert(ad->members);
|
assert(ad->members);
|
||||||
Dsymbol *s = ad->search(loc, ident, 0);
|
Dsymbol *s = ad->search(loc, ident, 0);
|
||||||
if (!s)
|
if (!s)
|
||||||
{ s = sc->search(loc, ident, NULL);
|
{
|
||||||
|
s = sc->search(loc, ident, NULL);
|
||||||
if (s)
|
if (s)
|
||||||
::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
|
::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
|
||||||
else
|
else
|
||||||
@@ -98,17 +89,24 @@ void AliasThis::semantic(Scope *sc)
|
|||||||
else if (ad->aliasthis && s != ad->aliasthis)
|
else if (ad->aliasthis && s != ad->aliasthis)
|
||||||
error("there can be only one alias this");
|
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
|
/* disable the alias this conversion so the implicit conversion check
|
||||||
* doesn't use it.
|
* doesn't use it.
|
||||||
*/
|
*/
|
||||||
/* This should use ad->aliasthis directly, but with static foreach and templates
|
ad->aliasthis = NULL;
|
||||||
* ad->type->sym might be different to ad.
|
|
||||||
*/
|
|
||||||
AggregateDeclaration *ad2 = ad->type->toDsymbol(NULL)->isAggregateDeclaration();
|
|
||||||
Dsymbol *save = ad2->aliasthis;
|
|
||||||
ad2->aliasthis = NULL;
|
|
||||||
|
|
||||||
if (Declaration *d = s->isDeclaration())
|
Dsymbol *sx = s;
|
||||||
|
if (sx->isAliasDeclaration())
|
||||||
|
sx = sx->toAlias();
|
||||||
|
Declaration *d = sx->isDeclaration();
|
||||||
|
if (d && !d->isTupleDeclaration())
|
||||||
{
|
{
|
||||||
Type *t = d->type;
|
Type *t = d->type;
|
||||||
assert(t);
|
assert(t);
|
||||||
@@ -118,7 +116,6 @@ void AliasThis::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ad2->aliasthis = save;
|
|
||||||
ad->aliasthis = s;
|
ad->aliasthis = s;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -136,5 +133,3 @@ void AliasThis::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring(ident->toChars());
|
buf->writestring(ident->toChars());
|
||||||
buf->writestring(" this;\n");
|
buf->writestring(" this;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
|
|
||||||
class AliasThis : public Dsymbol
|
class AliasThis : public Dsymbol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -38,5 +36,3 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
+6
-12
@@ -99,7 +99,7 @@ TypeTuple *TypeBasic::toArgTypes()
|
|||||||
t2 = Type::tfloat80;
|
t2 = Type::tfloat80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Tascii:
|
case Tchar:
|
||||||
t1 = Type::tuns8;
|
t1 = Type::tuns8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -127,16 +127,13 @@ TypeTuple *TypeBasic::toArgTypes()
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
TypeTuple *TypeVector::toArgTypes()
|
TypeTuple *TypeVector::toArgTypes()
|
||||||
{
|
{
|
||||||
return new TypeTuple(this);
|
return new TypeTuple(this);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
TypeTuple *TypeSArray::toArgTypes()
|
TypeTuple *TypeSArray::toArgTypes()
|
||||||
{
|
{
|
||||||
#if DMDV2
|
|
||||||
if (dim)
|
if (dim)
|
||||||
{
|
{
|
||||||
/* Should really be done as if it were a struct with dim members
|
/* Should really be done as if it were a struct with dim members
|
||||||
@@ -149,9 +146,6 @@ TypeTuple *TypeSArray::toArgTypes()
|
|||||||
return next->toArgTypes();
|
return next->toArgTypes();
|
||||||
}
|
}
|
||||||
return new TypeTuple(); // pass on the stack for efficiency
|
return new TypeTuple(); // pass on the stack for efficiency
|
||||||
#else
|
|
||||||
return new TypeTuple(); // pass on the stack for efficiency
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeTuple *TypeAArray::toArgTypes()
|
TypeTuple *TypeAArray::toArgTypes()
|
||||||
@@ -204,8 +198,8 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2)
|
|||||||
if (!t2)
|
if (!t2)
|
||||||
return t1;
|
return t1;
|
||||||
|
|
||||||
unsigned sz1 = t1->size(Loc());
|
unsigned sz1 = (unsigned)t1->size(Loc());
|
||||||
unsigned sz2 = t2->size(Loc());
|
unsigned sz2 = (unsigned)t2->size(Loc());
|
||||||
|
|
||||||
if (t1->ty != t2->ty &&
|
if (t1->ty != t2->ty &&
|
||||||
(t1->ty == Tfloat80 || t2->ty == Tfloat80))
|
(t1->ty == Tfloat80 || t2->ty == Tfloat80))
|
||||||
@@ -265,7 +259,7 @@ TypeTuple *TypeDArray::toArgTypes()
|
|||||||
if (global.params.is64bit && !global.params.isLP64)
|
if (global.params.is64bit && !global.params.isLP64)
|
||||||
{
|
{
|
||||||
// For AMD64 ILP32 ABI, D arrays fit into a single integer register.
|
// 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);
|
Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
|
||||||
if (t)
|
if (t)
|
||||||
return new TypeTuple(t);
|
return new TypeTuple(t);
|
||||||
@@ -281,7 +275,7 @@ TypeTuple *TypeDelegate::toArgTypes()
|
|||||||
if (global.params.is64bit && !global.params.isLP64)
|
if (global.params.is64bit && !global.params.isLP64)
|
||||||
{
|
{
|
||||||
// For AMD64 ILP32 ABI, delegates fit into a single integer register.
|
// 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);
|
Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
|
||||||
if (t)
|
if (t)
|
||||||
return new TypeTuple(t);
|
return new TypeTuple(t);
|
||||||
@@ -360,7 +354,7 @@ TypeTuple *TypeStruct::toArgTypes()
|
|||||||
goto Lmemory;
|
goto Lmemory;
|
||||||
|
|
||||||
// Fields that overlap the 8byte boundary 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)
|
if (f->offset < 8 && (f->offset + fieldsz) > 8)
|
||||||
goto Lmemory;
|
goto Lmemory;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-34
@@ -272,23 +272,12 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
|
|||||||
* return p;
|
* return p;
|
||||||
*/
|
*/
|
||||||
Parameter *p = (*fparams)[0 /*fparams->dim - 1*/];
|
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)
|
// foreach (i; 0 .. p.length)
|
||||||
Statement *s1 = new ForeachRangeStatement(Loc(), TOKforeach,
|
Statement *s1 = new ForeachRangeStatement(Loc(), TOKforeach,
|
||||||
new Parameter(0, NULL, Id::p, NULL),
|
new Parameter(0, NULL, Id::p, NULL),
|
||||||
new IntegerExp(Loc(), 0, Type::tsize_t),
|
new IntegerExp(Loc(), 0, Type::tsize_t),
|
||||||
new ArrayLengthExp(Loc(), new IdentifierExp(Loc(), p->ident)),
|
new ArrayLengthExp(Loc(), new IdentifierExp(Loc(), p->ident)),
|
||||||
new ExpStatement(Loc(), loopbody));
|
new ExpStatement(Loc(), loopbody));
|
||||||
#endif
|
|
||||||
//printf("%s\n", s1->toChars());
|
//printf("%s\n", s1->toChars());
|
||||||
Statement *s2 = new ReturnStatement(Loc(), new IdentifierExp(Loc(), p->ident));
|
Statement *s2 = new ReturnStatement(Loc(), new IdentifierExp(Loc(), p->ident));
|
||||||
//printf("s2: %s\n", s2->toChars());
|
//printf("s2: %s\n", s2->toChars());
|
||||||
@@ -316,7 +305,14 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
|
|||||||
sc->linkage = LINKc;
|
sc->linkage = LINKc;
|
||||||
fd->semantic(sc);
|
fd->semantic(sc);
|
||||||
fd->semantic2(sc);
|
fd->semantic2(sc);
|
||||||
|
unsigned errors = global.startGagging();
|
||||||
fd->semantic3(sc);
|
fd->semantic3(sc);
|
||||||
|
if (global.endGagging(errors))
|
||||||
|
{
|
||||||
|
fd->type = Type::terror;
|
||||||
|
fd->errors = true;
|
||||||
|
fd->fbody = NULL;
|
||||||
|
}
|
||||||
sc->pop();
|
sc->pop();
|
||||||
|
|
||||||
if (op->cFunc)
|
if (op->cFunc)
|
||||||
@@ -344,6 +340,7 @@ bool isArrayOpValid(Expression *e)
|
|||||||
}
|
}
|
||||||
Type *tb = e->type->toBasetype();
|
Type *tb = e->type->toBasetype();
|
||||||
|
|
||||||
|
BinExp *be;
|
||||||
if ( (tb->ty == Tarray) || (tb->ty == Tsarray) )
|
if ( (tb->ty == Tarray) || (tb->ty == Tsarray) )
|
||||||
{
|
{
|
||||||
switch (e->op)
|
switch (e->op)
|
||||||
@@ -365,11 +362,14 @@ bool isArrayOpValid(Expression *e)
|
|||||||
case TOKxorass:
|
case TOKxorass:
|
||||||
case TOKandass:
|
case TOKandass:
|
||||||
case TOKorass:
|
case TOKorass:
|
||||||
#if DMDV2
|
|
||||||
case TOKpow:
|
case TOKpow:
|
||||||
case TOKpowass:
|
case TOKpowass:
|
||||||
#endif
|
be = (BinExp *)e;
|
||||||
return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2);
|
return isArrayOpValid(be->e1) && isArrayOpValid(be->e2);
|
||||||
|
|
||||||
|
case TOKconstruct:
|
||||||
|
be = (BinExp *)e;
|
||||||
|
return be->e1->op == TOKslice && isArrayOpValid(be->e2);
|
||||||
|
|
||||||
case TOKcall:
|
case TOKcall:
|
||||||
return false; // TODO: Decide if [] is required after arrayop calls.
|
return false; // TODO: Decide if [] is required after arrayop calls.
|
||||||
@@ -395,15 +395,15 @@ Expression *BinExp::arrayOp(Scope *sc)
|
|||||||
|
|
||||||
Type *tb = type->toBasetype();
|
Type *tb = type->toBasetype();
|
||||||
assert(tb->ty == Tarray || tb->ty == Tsarray);
|
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");
|
error("Cannot perform array operations on void[] arrays");
|
||||||
return new ErrorExp();
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
|
if (!isArrayOpValid(this))
|
||||||
if (!isArrayOpValid(e2))
|
|
||||||
{
|
{
|
||||||
e2->error("invalid array operation %s (did you forget a [] ?)", toChars());
|
error("invalid array operation %s (did you forget a [] ?)", toChars());
|
||||||
return new ErrorExp();
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,11 +420,7 @@ Expression *BinExp::arrayOp(Scope *sc)
|
|||||||
|
|
||||||
/* Append deco of array element type
|
/* Append deco of array element type
|
||||||
*/
|
*/
|
||||||
#if DMDV2
|
|
||||||
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
|
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
|
||||||
#else
|
|
||||||
buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
buf.writeByte(0);
|
buf.writeByte(0);
|
||||||
char *name = buf.toChars();
|
char *name = buf.toChars();
|
||||||
@@ -440,6 +436,20 @@ Expression *BinExp::arrayOp(Scope *sc)
|
|||||||
if (!op)
|
if (!op)
|
||||||
op = buildArrayOp(ident, this, sc, loc);
|
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;
|
*pOp = op;
|
||||||
|
|
||||||
FuncDeclaration *fd = op->cFunc ? op->cFunc : op->dFunc;
|
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());
|
error("slice %s is not mutable", e1->toChars());
|
||||||
return new ErrorExp();
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
|
if (e1->op == TOKarrayliteral)
|
||||||
|
{
|
||||||
|
return e1->modifiableLvalue(sc, e1);
|
||||||
|
}
|
||||||
|
|
||||||
return BinExp::arrayOp(sc);
|
return BinExp::arrayOp(sc);
|
||||||
}
|
}
|
||||||
@@ -526,9 +540,7 @@ void BinAssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
|||||||
case TOKxorass: s = "Xorass"; break;
|
case TOKxorass: s = "Xorass"; break;
|
||||||
case TOKandass: s = "Andass"; break;
|
case TOKandass: s = "Andass"; break;
|
||||||
case TOKorass: s = "Orass"; break;
|
case TOKorass: s = "Orass"; break;
|
||||||
#if DMDV2
|
|
||||||
case TOKpowass: s = "Powass"; break;
|
case TOKpowass: s = "Powass"; break;
|
||||||
#endif
|
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
buf->writestring(s);
|
buf->writestring(s);
|
||||||
@@ -561,9 +573,7 @@ void BinExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
|||||||
case TOKxor: s = "Xor"; break;
|
case TOKxor: s = "Xor"; break;
|
||||||
case TOKand: s = "And"; break;
|
case TOKand: s = "And"; break;
|
||||||
case TOKor: s = "Or"; break;
|
case TOKor: s = "Or"; break;
|
||||||
#if DMDV2
|
|
||||||
case TOKpow: s = "Pow"; break;
|
case TOKpow: s = "Pow"; break;
|
||||||
#endif
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if (s)
|
if (s)
|
||||||
@@ -632,14 +642,12 @@ Expression *AssignExp::buildArrayLoop(Parameters *fparams)
|
|||||||
/* Evaluate assign expressions right to left
|
/* Evaluate assign expressions right to left
|
||||||
*/
|
*/
|
||||||
Expression *ex2 = e2->buildArrayLoop(fparams);
|
Expression *ex2 = e2->buildArrayLoop(fparams);
|
||||||
#if DMDV2
|
|
||||||
/* Need the cast because:
|
/* Need the cast because:
|
||||||
* b = c + p[i];
|
* b = c + p[i];
|
||||||
* where b is a byte fails because (c + p[i]) is an int
|
* where b is a byte fails because (c + p[i]) is an int
|
||||||
* which cannot be implicitly cast to byte.
|
* which cannot be implicitly cast to byte.
|
||||||
*/
|
*/
|
||||||
ex2 = new CastExp(Loc(), ex2, e1->type->nextOf());
|
ex2 = new CastExp(Loc(), ex2, e1->type->nextOf());
|
||||||
#endif
|
|
||||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||||
Parameter *param = (*fparams)[0];
|
Parameter *param = (*fparams)[0];
|
||||||
param->storageClass = 0;
|
param->storageClass = 0;
|
||||||
@@ -666,9 +674,7 @@ Expression *BinAssignExp::buildArrayLoop(Parameters *fparams)
|
|||||||
case TOKxorass: return new XorAssignExp(loc, ex1, ex2);
|
case TOKxorass: return new XorAssignExp(loc, ex1, ex2);
|
||||||
case TOKandass: return new AndAssignExp(loc, ex1, ex2);
|
case TOKandass: return new AndAssignExp(loc, ex1, ex2);
|
||||||
case TOKorass: return new OrAssignExp(loc, ex1, ex2);
|
case TOKorass: return new OrAssignExp(loc, ex1, ex2);
|
||||||
#if DMDV2
|
|
||||||
case TOKpowass: return new PowAssignExp(loc, ex1, ex2);
|
case TOKpowass: return new PowAssignExp(loc, ex1, ex2);
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -701,9 +707,7 @@ Expression *BinExp::buildArrayLoop(Parameters *fparams)
|
|||||||
case TOKxor:
|
case TOKxor:
|
||||||
case TOKand:
|
case TOKand:
|
||||||
case TOKor:
|
case TOKor:
|
||||||
#if DMDV2
|
|
||||||
case TOKpow:
|
case TOKpow:
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
/* Evaluate assign expressions left to right
|
/* Evaluate assign expressions left to right
|
||||||
*/
|
*/
|
||||||
@@ -755,10 +759,8 @@ int Expression::isArrayOperand()
|
|||||||
case TOKxorass:
|
case TOKxorass:
|
||||||
case TOKandass:
|
case TOKandass:
|
||||||
case TOKorass:
|
case TOKorass:
|
||||||
#if DMDV2
|
|
||||||
case TOKpow:
|
case TOKpow:
|
||||||
case TOKpowass:
|
case TOKpowass:
|
||||||
#endif
|
|
||||||
case TOKneg:
|
case TOKneg:
|
||||||
case TOKtilde:
|
case TOKtilde:
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+4
-2
@@ -56,14 +56,16 @@ typedef Array<class AliasDeclaration> AliasDeclarations;
|
|||||||
|
|
||||||
typedef Array<class Module> Modules;
|
typedef Array<class Module> Modules;
|
||||||
|
|
||||||
typedef Array<class File> Files;
|
typedef Array<struct File> Files;
|
||||||
|
|
||||||
typedef Array<class CaseStatement> CaseStatements;
|
typedef Array<class CaseStatement> CaseStatements;
|
||||||
|
|
||||||
typedef Array<class CompoundStatement> CompoundStatements;
|
typedef Array<class ScopeStatement> ScopeStatements;
|
||||||
|
|
||||||
typedef Array<class GotoCaseStatement> GotoCaseStatements;
|
typedef Array<class GotoCaseStatement> GotoCaseStatements;
|
||||||
|
|
||||||
|
typedef Array<class GotoStatement> GotoStatements;
|
||||||
|
|
||||||
typedef Array<class ReturnStatement> ReturnStatements;
|
typedef Array<class ReturnStatement> ReturnStatements;
|
||||||
|
|
||||||
typedef Array<class TemplateInstance> TemplateInstances;
|
typedef Array<class TemplateInstance> TemplateInstances;
|
||||||
|
|||||||
+25
-14
@@ -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);
|
//printf("AttribDeclaration::addComment %s\n", comment);
|
||||||
if (comment)
|
if (comment)
|
||||||
@@ -288,10 +288,10 @@ bool AttribDeclaration::hasStaticCtorOrDtor()
|
|||||||
{
|
{
|
||||||
Dsymbol *s = (*d)[i];
|
Dsymbol *s = (*d)[i];
|
||||||
if (s->hasStaticCtorOrDtor())
|
if (s->hasStaticCtorOrDtor())
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *AttribDeclaration::kind()
|
const char *AttribDeclaration::kind()
|
||||||
@@ -497,11 +497,11 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
|
|||||||
{ STCalias, TOKalias },
|
{ STCalias, TOKalias },
|
||||||
{ STCout, TOKout },
|
{ STCout, TOKout },
|
||||||
{ STCin, TOKin },
|
{ STCin, TOKin },
|
||||||
#if DMDV2
|
|
||||||
{ STCmanifest, TOKenum },
|
{ STCmanifest, TOKenum },
|
||||||
{ STCimmutable, TOKimmutable },
|
{ STCimmutable, TOKimmutable },
|
||||||
{ STCshared, TOKshared },
|
{ STCshared, TOKshared },
|
||||||
{ STCnothrow, TOKnothrow },
|
{ STCnothrow, TOKnothrow },
|
||||||
|
{ STCwild, TOKwild },
|
||||||
{ STCpure, TOKpure },
|
{ STCpure, TOKpure },
|
||||||
{ STCref, TOKref },
|
{ STCref, TOKref },
|
||||||
{ STCtls },
|
{ STCtls },
|
||||||
@@ -511,7 +511,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
|
|||||||
{ STCtrusted, TOKat, "trusted" },
|
{ STCtrusted, TOKat, "trusted" },
|
||||||
{ STCsystem, TOKat, "system" },
|
{ STCsystem, TOKat, "system" },
|
||||||
{ STCdisable, TOKat, "disable" },
|
{ STCdisable, TOKat, "disable" },
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
|
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";
|
return "__thread";
|
||||||
|
|
||||||
TOK tok = table[i].tok;
|
TOK tok = table[i].tok;
|
||||||
#if DMDV2
|
|
||||||
if (tok == TOKat)
|
if (tok == TOKat)
|
||||||
{
|
{
|
||||||
tmp[0] = '@';
|
tmp[0] = '@';
|
||||||
@@ -533,7 +531,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
return Token::toChars(tok);
|
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)
|
void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, PROT protection)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
@@ -1080,7 +1083,6 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
goto Lnodecl;
|
goto Lnodecl;
|
||||||
}
|
}
|
||||||
#if DMDV2
|
|
||||||
else if (ident == Id::startaddress)
|
else if (ident == Id::startaddress)
|
||||||
{
|
{
|
||||||
if (!args || args->dim != 1)
|
if (!args || args->dim != 1)
|
||||||
@@ -1102,7 +1104,6 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
goto Lnodecl;
|
goto Lnodecl;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else if (ident == Id::mangle)
|
else if (ident == Id::mangle)
|
||||||
{
|
{
|
||||||
if (!args || args->dim != 1)
|
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
|
/* Because addComment is called by the parser, if we called
|
||||||
* include() it would define a version before it was used.
|
* 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;
|
this->sd = sd;
|
||||||
if (memnum == 0)
|
if (memnum == 0)
|
||||||
{ /* No members yet, so parse the mixin now
|
{
|
||||||
|
/* No members yet, so parse the mixin now
|
||||||
*/
|
*/
|
||||||
compileIt(sc);
|
compileIt(sc);
|
||||||
memnum |= AttribDeclaration::addMember(sc, sd, memnum);
|
memnum |= AttribDeclaration::addMember(sc, sd, memnum);
|
||||||
@@ -1624,13 +1626,13 @@ void CompileDeclaration::compileIt(Scope *sc)
|
|||||||
exp = exp->ctfeInterpret();
|
exp = exp->ctfeInterpret();
|
||||||
StringExp *se = exp->toString();
|
StringExp *se = exp->toString();
|
||||||
if (!se)
|
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
|
else
|
||||||
{
|
{
|
||||||
se = se->toUTF8(sc);
|
se = se->toUTF8(sc);
|
||||||
Parser p(sc->module, (utf8_t *)se->string, se->len, 0);
|
Parser p(loc, sc->module, (utf8_t *)se->string, se->len, 0);
|
||||||
p.scanloc = loc;
|
|
||||||
p.nextToken();
|
p.nextToken();
|
||||||
unsigned errors = global.errors;
|
unsigned errors = global.errors;
|
||||||
decl = p.parseDeclDefs(0);
|
decl = p.parseDeclDefs(0);
|
||||||
@@ -1650,6 +1652,15 @@ void CompileDeclaration::semantic(Scope *sc)
|
|||||||
compileIt(sc);
|
compileIt(sc);
|
||||||
AttribDeclaration::addMember(sc, sd, 0);
|
AttribDeclaration::addMember(sc, sd, 0);
|
||||||
compiled = 1;
|
compiled = 1;
|
||||||
|
|
||||||
|
if (scope && decl)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
|
{
|
||||||
|
Dsymbol *s = (*decl)[i];
|
||||||
|
s->setScope(scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AttribDeclaration::semantic(sc);
|
AttribDeclaration::semantic(sc);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -46,7 +46,7 @@ public:
|
|||||||
void semantic2(Scope *sc);
|
void semantic2(Scope *sc);
|
||||||
void semantic3(Scope *sc);
|
void semantic3(Scope *sc);
|
||||||
void inlineScan();
|
void inlineScan();
|
||||||
void addComment(utf8_t *comment);
|
void addComment(const utf8_t *comment);
|
||||||
void emitComment(Scope *sc);
|
void emitComment(Scope *sc);
|
||||||
const char *kind();
|
const char *kind();
|
||||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||||
@@ -119,6 +119,7 @@ public:
|
|||||||
void importAll(Scope *sc);
|
void importAll(Scope *sc);
|
||||||
void setScope(Scope *sc);
|
void setScope(Scope *sc);
|
||||||
void semantic(Scope *sc);
|
void semantic(Scope *sc);
|
||||||
|
void emitComment(Scope *sc);
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
|
|
||||||
static void protectionToCBuffer(OutBuffer *buf, PROT protection);
|
static void protectionToCBuffer(OutBuffer *buf, PROT protection);
|
||||||
@@ -184,7 +185,7 @@ public:
|
|||||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||||
void emitComment(Scope *sc);
|
void emitComment(Scope *sc);
|
||||||
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
|
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
|
||||||
void addComment(utf8_t *comment);
|
void addComment(const utf8_t *comment);
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
void toJson(JsonOut *json);
|
void toJson(JsonOut *json);
|
||||||
void importAll(Scope *sc);
|
void importAll(Scope *sc);
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "id.h"
|
#include "id.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
* Determine if function is a builtin one that we can
|
* 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;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
+12
-12
@@ -23,7 +23,7 @@
|
|||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
|
|
||||||
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow);
|
bool Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow);
|
||||||
int lambdaCanThrow(Expression *e, void *param);
|
int lambdaCanThrow(Expression *e, void *param);
|
||||||
|
|
||||||
/********************************************
|
/********************************************
|
||||||
@@ -40,11 +40,11 @@ struct CanThrow
|
|||||||
bool mustnot;
|
bool mustnot;
|
||||||
};
|
};
|
||||||
|
|
||||||
int Expression::canThrow(bool mustNotThrow)
|
bool Expression::canThrow(bool mustNotThrow)
|
||||||
{
|
{
|
||||||
//printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars());
|
//printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars());
|
||||||
CanThrow ct;
|
CanThrow ct;
|
||||||
ct.can = FALSE;
|
ct.can = false;
|
||||||
ct.mustnot = mustNotThrow;
|
ct.mustnot = mustNotThrow;
|
||||||
apply(&lambdaCanThrow, &ct);
|
apply(&lambdaCanThrow, &ct);
|
||||||
return ct.can;
|
return ct.can;
|
||||||
@@ -81,7 +81,7 @@ int lambdaCanThrow(Expression *e, void *param)
|
|||||||
{
|
{
|
||||||
if (pct->mustnot)
|
if (pct->mustnot)
|
||||||
e->error("'%s' is not nothrow", ce->f ? ce->f->toPrettyChars() : ce->e1->toChars());
|
e->error("'%s' is not nothrow", ce->f ? ce->f->toPrettyChars() : ce->e1->toChars());
|
||||||
pct->can = TRUE;
|
pct->can = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ int lambdaCanThrow(Expression *e, void *param)
|
|||||||
{
|
{
|
||||||
if (pct->mustnot)
|
if (pct->mustnot)
|
||||||
e->error("constructor %s is not nothrow", ne->member->toChars());
|
e->error("constructor %s is not nothrow", ne->member->toChars());
|
||||||
pct->can = TRUE;
|
pct->can = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// regard storage allocation failures as not recoverable
|
// regard storage allocation failures as not recoverable
|
||||||
@@ -126,7 +126,7 @@ int lambdaCanThrow(Expression *e, void *param)
|
|||||||
{
|
{
|
||||||
if (pct->mustnot)
|
if (pct->mustnot)
|
||||||
e->error("'%s' is not nothrow", sd->postblit->toPrettyChars());
|
e->error("'%s' is not nothrow", sd->postblit->toPrettyChars());
|
||||||
pct->can = TRUE;
|
pct->can = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ int lambdaCanThrow(Expression *e, void *param)
|
|||||||
* Mirrors logic in Dsymbol_toElem().
|
* Mirrors logic in Dsymbol_toElem().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
bool Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
||||||
{
|
{
|
||||||
AttribDeclaration *ad;
|
AttribDeclaration *ad;
|
||||||
VarDeclaration *vd;
|
VarDeclaration *vd;
|
||||||
@@ -164,7 +164,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
|||||||
{
|
{
|
||||||
s = (*decl)[i];
|
s = (*decl)[i];
|
||||||
if (Dsymbol_canThrow(s, mustNotThrow))
|
if (Dsymbol_canThrow(s, mustNotThrow))
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
|||||||
if (vd->init)
|
if (vd->init)
|
||||||
{ ExpInitializer *ie = vd->init->isExpInitializer();
|
{ ExpInitializer *ie = vd->init->isExpInitializer();
|
||||||
if (ie && ie->exp->canThrow(mustNotThrow))
|
if (ie && ie->exp->canThrow(mustNotThrow))
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
if (vd->edtor && !vd->noscope)
|
if (vd->edtor && !vd->noscope)
|
||||||
return vd->edtor->canThrow(mustNotThrow);
|
return vd->edtor->canThrow(mustNotThrow);
|
||||||
@@ -197,7 +197,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
|||||||
{
|
{
|
||||||
Dsymbol *sm = (*tm->members)[i];
|
Dsymbol *sm = (*tm->members)[i];
|
||||||
if (Dsymbol_canThrow(sm, mustNotThrow))
|
if (Dsymbol_canThrow(sm, mustNotThrow))
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,10 +210,10 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
|||||||
if (eo->op == TOKdsymbol)
|
if (eo->op == TOKdsymbol)
|
||||||
{ DsymbolExp *se = (DsymbolExp *)eo;
|
{ DsymbolExp *se = (DsymbolExp *)eo;
|
||||||
if (Dsymbol_canThrow(se->s, mustNotThrow))
|
if (Dsymbol_canThrow(se->s, mustNotThrow))
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-73
@@ -39,45 +39,12 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t)
|
|||||||
MATCH match = implicitConvTo(t);
|
MATCH match = implicitConvTo(t);
|
||||||
if (match)
|
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))
|
if (match == MATCHconst && type->constConv(t))
|
||||||
{
|
{
|
||||||
Expression *e = copy();
|
Expression *e = copy();
|
||||||
e->type = t;
|
e->type = t;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return castTo(sc, t);
|
return castTo(sc, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,9 +145,8 @@ MATCH Expression::implicitConvTo(Type *t)
|
|||||||
if (type->isintegral() && t->isintegral() &&
|
if (type->isintegral() && t->isintegral() &&
|
||||||
type->isTypeBasic() && t->isTypeBasic())
|
type->isTypeBasic() && t->isTypeBasic())
|
||||||
{ IntRange src = this->getIntRange() DUMP;
|
{ IntRange src = this->getIntRange() DUMP;
|
||||||
IntRange targetUnsigned = IntRange::fromType(t, /*isUnsigned*/true) DUMP;
|
IntRange target = IntRange::fromType(t) DUMP;
|
||||||
IntRange targetSigned = IntRange::fromType(t, /*isUnsigned*/false) DUMP;
|
if (target.contains(src))
|
||||||
if (targetUnsigned.contains(src) || targetSigned.contains(src))
|
|
||||||
return MATCHconvert;
|
return MATCHconvert;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +192,8 @@ MATCH IntegerExp::implicitConvTo(Type *t)
|
|||||||
if (t->ty == Tvector)
|
if (t->ty == Tvector)
|
||||||
{ TypeVector *tv = (TypeVector *)t;
|
{ TypeVector *tv = (TypeVector *)t;
|
||||||
TypeBasic *tb = tv->elementType();
|
TypeBasic *tb = tv->elementType();
|
||||||
|
if (tb->ty == Tvoid)
|
||||||
|
goto Lno;
|
||||||
toty = tb->ty;
|
toty = tb->ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +410,6 @@ MATCH NullExp::implicitConvTo(Type *t)
|
|||||||
return Expression::implicitConvTo(t);
|
return Expression::implicitConvTo(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
MATCH StructLiteralExp::implicitConvTo(Type *t)
|
MATCH StructLiteralExp::implicitConvTo(Type *t)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -471,7 +438,6 @@ MATCH StructLiteralExp::implicitConvTo(Type *t)
|
|||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
MATCH StringExp::implicitConvTo(Type *t)
|
MATCH StringExp::implicitConvTo(Type *t)
|
||||||
{
|
{
|
||||||
@@ -645,6 +611,27 @@ MATCH AssocArrayLiteralExp::implicitConvTo(Type *t)
|
|||||||
return Expression::implicitConvTo(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)
|
MATCH CallExp::implicitConvTo(Type *t)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -1025,7 +1012,7 @@ Type *SliceExp::toStaticArrayType()
|
|||||||
Expression *upr = this->upr->optimize(WANTvalue);
|
Expression *upr = this->upr->optimize(WANTvalue);
|
||||||
if (lwr->isConst() && upr->isConst())
|
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);
|
return TypeSArray::makeType(loc, type->toBasetype()->nextOf(), len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1086,19 +1073,8 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
|||||||
{
|
{
|
||||||
//printf("Converting [dim] to *\n");
|
//printf("Converting [dim] to *\n");
|
||||||
|
|
||||||
if (typeb->size(loc) == 0)
|
e = new AddrExp(loc, e);
|
||||||
e = new NullExp(loc);
|
|
||||||
else
|
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
if (typeb->ty == Tstruct)
|
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()))
|
else if (typeb->implicitConvTo(tb) == MATCHconst && t->equals(type->constOf()))
|
||||||
{
|
{
|
||||||
Expression *e = copy();
|
e = copy();
|
||||||
e->type = t;
|
e->type = t;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -1480,7 +1456,7 @@ L2:
|
|||||||
// See if need to truncate or extend the literal
|
// See if need to truncate or extend the literal
|
||||||
if (tb->ty == Tsarray)
|
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);
|
//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 = new SymOffExp(loc, f, 0);
|
||||||
e->type = t;
|
e->type = t;
|
||||||
}
|
}
|
||||||
#if DMDV2
|
|
||||||
f->tookAddressOf++;
|
f->tookAddressOf++;
|
||||||
#endif
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1965,7 +1939,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
|
|||||||
{
|
{
|
||||||
if (to->ty == Tdelegate ||
|
if (to->ty == Tdelegate ||
|
||||||
to->ty == Tpointer && to->nextOf()->ty == Tfunction)
|
to->ty == Tpointer && to->nextOf()->ty == Tfunction)
|
||||||
{ fd->treq = to;
|
{
|
||||||
|
fd->treq = to;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -1985,7 +1960,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (td)
|
if (td)
|
||||||
{ /// Parameter types inference from
|
{
|
||||||
|
// Parameter types inference from 'to'
|
||||||
assert(td->scope);
|
assert(td->scope);
|
||||||
if (t->ty == Tfunction)
|
if (t->ty == Tfunction)
|
||||||
{
|
{
|
||||||
@@ -2005,10 +1981,12 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
|
|||||||
{
|
{
|
||||||
TemplateParameter *tp = (*td->parameters)[i];
|
TemplateParameter *tp = (*td->parameters)[i];
|
||||||
for (size_t u = 0; u < dim; u++)
|
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 &&
|
if (p->type->ty == Tident &&
|
||||||
((TypeIdentifier *)p->type)->ident == tp->ident)
|
((TypeIdentifier *)p->type)->ident == tp->ident)
|
||||||
{ p = Parameter::getNth(tfv->parameters, u);
|
{
|
||||||
|
p = Parameter::getNth(tfv->parameters, u);
|
||||||
Type *tprm = p->type;
|
Type *tprm = p->type;
|
||||||
if (tprm->reliesOnTident(tparams))
|
if (tprm->reliesOnTident(tparams))
|
||||||
goto L1;
|
goto L1;
|
||||||
@@ -2036,7 +2014,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
|
|||||||
fld->treq = NULL;
|
fld->treq = NULL;
|
||||||
|
|
||||||
if (e->op == TOKfunction)
|
if (e->op == TOKfunction)
|
||||||
{ FuncExp *fe = (FuncExp *)e;
|
{
|
||||||
|
FuncExp *fe = (FuncExp *)e;
|
||||||
assert(fe->td == NULL);
|
assert(fe->td == NULL);
|
||||||
e = fe->inferType(to, flag);
|
e = fe->inferType(to, flag);
|
||||||
}
|
}
|
||||||
@@ -2065,7 +2044,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters
|
|||||||
}
|
}
|
||||||
L1:
|
L1:
|
||||||
if (!flag && !e)
|
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();
|
e = new ErrorExp();
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
@@ -2700,6 +2680,15 @@ Lcc:
|
|||||||
e2 = e2->castTo(sc, t);
|
e2 = e2->castTo(sc, t);
|
||||||
goto Lagain;
|
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 &&
|
else if (e1->isArrayOperand() && t1->ty == Tarray &&
|
||||||
e2->implicitConvTo(t1->nextOf()))
|
e2->implicitConvTo(t1->nextOf()))
|
||||||
{ // T[] op T
|
{ // T[] op T
|
||||||
@@ -2770,6 +2759,8 @@ Expression *BinExp::typeCombine(Scope *sc)
|
|||||||
goto Lerror;
|
goto Lerror;
|
||||||
else if (t1->ty == Tclass && t2->ty == Tclass)
|
else if (t1->ty == Tclass && t2->ty == Tclass)
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
|
else if (t1->ty == Taarray && t2->ty == Taarray)
|
||||||
|
goto Lerror;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!typeMerge(sc, this, &type, &e1, &e2))
|
if (!typeMerge(sc, this, &type, &e1, &e2))
|
||||||
@@ -2930,12 +2921,11 @@ IntRange DivExp::getIntRange()
|
|||||||
return Expression::getIntRange() DUMP;
|
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)]
|
// [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] = {
|
SignExtendedNumber bdy[4];
|
||||||
ir1.imin / ir2.imin,
|
bdy[0] = ir1.imin / ir2.imin;
|
||||||
ir1.imin / ir2.imax,
|
bdy[1] = ir1.imin / ir2.imax;
|
||||||
ir1.imax / ir2.imin,
|
bdy[2] = ir1.imax / ir2.imin;
|
||||||
ir1.imax / ir2.imax
|
bdy[3] = ir1.imax / ir2.imax;
|
||||||
};
|
|
||||||
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
|
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2945,12 +2935,11 @@ IntRange MulExp::getIntRange()
|
|||||||
IntRange ir2 = e2->getIntRange();
|
IntRange ir2 = e2->getIntRange();
|
||||||
|
|
||||||
// [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)]
|
// [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)]
|
||||||
SignExtendedNumber bdy[4] = {
|
SignExtendedNumber bdy[4];
|
||||||
ir1.imin * ir2.imin,
|
bdy[0] = ir1.imin * ir2.imin;
|
||||||
ir1.imin * ir2.imax,
|
bdy[1] = ir1.imin * ir2.imax;
|
||||||
ir1.imax * ir2.imin,
|
bdy[2] = ir1.imax * ir2.imin;
|
||||||
ir1.imax * ir2.imax
|
bdy[3] = ir1.imax * ir2.imax;
|
||||||
};
|
|
||||||
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
|
return IntRange::fromNumbers4(bdy).cast(type) DUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-32
@@ -155,7 +155,6 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
|
|||||||
Type::typeinfotypelist = this;
|
Type::typeinfotypelist = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (id == Id::TypeInfo_Const)
|
if (id == Id::TypeInfo_Const)
|
||||||
{ if (!inObject)
|
{ if (!inObject)
|
||||||
error("%s", msg);
|
error("%s", msg);
|
||||||
@@ -185,7 +184,6 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
|
|||||||
error("%s", msg);
|
error("%s", msg);
|
||||||
Type::typeinfovector = this;
|
Type::typeinfovector = this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == Id::Object)
|
if (id == Id::Object)
|
||||||
@@ -213,16 +211,8 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !MODULEINFO_IS_STRUCT
|
#if !MODULEINFO_IS_STRUCT
|
||||||
#ifdef DMDV2
|
|
||||||
if (id == Id::ModuleInfo && !Module::moduleinfo)
|
if (id == Id::ModuleInfo && !Module::moduleinfo)
|
||||||
Module::moduleinfo = this;
|
Module::moduleinfo = this;
|
||||||
#else
|
|
||||||
if (id == Id::ModuleInfo)
|
|
||||||
{ if (Module::moduleinfo)
|
|
||||||
error("%s", msg);
|
|
||||||
Module::moduleinfo = this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,10 +371,21 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
goto L7;
|
goto L7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
|
if (tc->sym->scope)
|
||||||
{ // Try to resolve forward reference
|
{
|
||||||
if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope)
|
// Try to resolve forward reference
|
||||||
tc->sym->semantic(NULL);
|
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)
|
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
|
||||||
{
|
{
|
||||||
@@ -399,10 +400,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
scope->module->addDeferredSemantic(this);
|
scope->module->addDeferredSemantic(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{ baseClass = tc->sym;
|
|
||||||
b->base = baseClass;
|
|
||||||
}
|
|
||||||
L7: ;
|
L7: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,10 +445,10 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
error("inherits from duplicate interface %s", b2->base->toChars());
|
error("inherits from duplicate interface %s", b2->base->toChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tc->sym->symtab)
|
if (tc->sym->scope)
|
||||||
{ // Try to resolve forward reference
|
{
|
||||||
if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope)
|
// Try to resolve forward reference
|
||||||
tc->sym->semantic(NULL);
|
tc->sym->semantic(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
b->base = tc->sym;
|
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).
|
* Return 1 if function is hidden (not findable through search).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
int isf(void *param, Dsymbol *s)
|
int isf(void *param, Dsymbol *s)
|
||||||
{
|
{
|
||||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||||
@@ -1044,7 +1040,6 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
|
|||||||
return !fd->parent->isTemplateMixin();
|
return !fd->parent->isTemplateMixin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Find virtual function matching identifier and type.
|
* Find virtual function matching identifier and type.
|
||||||
@@ -1172,7 +1167,6 @@ int ClassDeclaration::isCOMinterface()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
int ClassDeclaration::isCPPclass()
|
int ClassDeclaration::isCPPclass()
|
||||||
{
|
{
|
||||||
return cpp;
|
return cpp;
|
||||||
@@ -1182,7 +1176,6 @@ int ClassDeclaration::isCPPinterface()
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
@@ -1366,10 +1359,10 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
|||||||
baseclasses->remove(i);
|
baseclasses->remove(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!b->base->symtab)
|
if (b->base->scope)
|
||||||
{ // Try to resolve forward reference
|
{
|
||||||
if (doAncestorsSemantic == SemanticIn && b->base->scope)
|
// Try to resolve forward reference
|
||||||
b->base->semantic(NULL);
|
b->base->semantic(NULL);
|
||||||
}
|
}
|
||||||
if (!b->base->symtab || b->base->scope || b->base->inuse)
|
if (!b->base->symtab || b->base->scope || b->base->inuse)
|
||||||
{
|
{
|
||||||
@@ -1605,12 +1598,10 @@ int InterfaceDeclaration::isCOMinterface()
|
|||||||
return com;
|
return com;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
int InterfaceDeclaration::isCPPinterface()
|
int InterfaceDeclaration::isCPPinterface()
|
||||||
{
|
{
|
||||||
return cpp;
|
return cpp;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*******************************************
|
/*******************************************
|
||||||
*/
|
*/
|
||||||
|
|||||||
+12
-11
@@ -76,6 +76,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc)
|
|||||||
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
|
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
|
||||||
global.speculativeGag = global.gag;
|
global.speculativeGag = global.gag;
|
||||||
sc = sc->push();
|
sc = sc->push();
|
||||||
|
sc->tinst = NULL;
|
||||||
sc->speculative = true;
|
sc->speculative = true;
|
||||||
|
|
||||||
for (size_t i = 0; i < 2; i++)
|
for (size_t i = 0; i < 2; i++)
|
||||||
@@ -196,7 +197,11 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
|||||||
if (dtor || postblit)
|
if (dtor || postblit)
|
||||||
{
|
{
|
||||||
if (dtor)
|
if (dtor)
|
||||||
|
{
|
||||||
stc = mergeFuncAttrs(stc, dtor->storage_class);
|
stc = mergeFuncAttrs(stc, dtor->storage_class);
|
||||||
|
if (stc & STCsafe)
|
||||||
|
stc = (stc & ~STCsafe) | STCtrusted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -241,7 +246,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
|||||||
{
|
{
|
||||||
tmp = new VarDeclaration(loc, type, idtmp, new VoidInitializer(loc));
|
tmp = new VarDeclaration(loc, type, idtmp, new VoidInitializer(loc));
|
||||||
tmp->noscope = 1;
|
tmp->noscope = 1;
|
||||||
tmp->storage_class |= STCctfe;
|
tmp->storage_class |= STCtemp | STCctfe;
|
||||||
e = new DeclarationExp(loc, tmp);
|
e = new DeclarationExp(loc, tmp);
|
||||||
ec = new AssignExp(loc,
|
ec = new AssignExp(loc,
|
||||||
new VarExp(loc, tmp),
|
new VarExp(loc, tmp),
|
||||||
@@ -305,7 +310,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
|||||||
Dsymbols *decldefs = new Dsymbols();
|
Dsymbols *decldefs = new Dsymbols();
|
||||||
decldefs->push(s);
|
decldefs->push(s);
|
||||||
TemplateDeclaration *tempdecl =
|
TemplateDeclaration *tempdecl =
|
||||||
new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0);
|
new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs);
|
||||||
s = tempdecl;
|
s = tempdecl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -419,6 +424,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
|
|||||||
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
|
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
|
||||||
global.speculativeGag = global.gag;
|
global.speculativeGag = global.gag;
|
||||||
sc = sc->push();
|
sc = sc->push();
|
||||||
|
sc->tinst = NULL;
|
||||||
sc->speculative = true;
|
sc->speculative = true;
|
||||||
|
|
||||||
for (size_t j = 0; j < 2; j++)
|
for (size_t j = 0; j < 2; j++)
|
||||||
@@ -483,7 +489,7 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
|
|||||||
{
|
{
|
||||||
TypeFunction *tfeqptr;
|
TypeFunction *tfeqptr;
|
||||||
{
|
{
|
||||||
Scope sc;
|
Scope scx;
|
||||||
|
|
||||||
/* const bool opEquals(ref const S s);
|
/* 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));
|
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
|
||||||
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
|
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
|
||||||
tfeqptr->mod = MODconst;
|
tfeqptr->mod = MODconst;
|
||||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &sc);
|
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &scx);
|
||||||
}
|
}
|
||||||
fd = fd->overloadExactMatch(tfeqptr);
|
fd = fd->overloadExactMatch(tfeqptr);
|
||||||
if (fd)
|
if (fd)
|
||||||
@@ -569,7 +575,7 @@ FuncDeclaration *StructDeclaration::buildXopCmp(Scope *sc)
|
|||||||
{
|
{
|
||||||
TypeFunction *tfcmpptr;
|
TypeFunction *tfcmpptr;
|
||||||
{
|
{
|
||||||
Scope sc;
|
Scope scx;
|
||||||
|
|
||||||
/* const int opCmp(ref const S s);
|
/* 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));
|
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
|
||||||
tfcmpptr = new TypeFunction(parameters, Type::tint32, 0, LINKd);
|
tfcmpptr = new TypeFunction(parameters, Type::tint32, 0, LINKd);
|
||||||
tfcmpptr->mod = MODconst;
|
tfcmpptr->mod = MODconst;
|
||||||
tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &sc);
|
tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &scx);
|
||||||
}
|
}
|
||||||
fd = fd->overloadExactMatch(tfcmpptr);
|
fd = fd->overloadExactMatch(tfcmpptr);
|
||||||
if (fd)
|
if (fd)
|
||||||
@@ -758,7 +764,6 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
|
|||||||
* and the ordering changes (runs forward instead of backwards).
|
* and the ordering changes (runs forward instead of backwards).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||||
{
|
{
|
||||||
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
|
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
|
||||||
@@ -864,8 +869,6 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*****************************************
|
/*****************************************
|
||||||
* Create inclusive destructor for struct/class by aggregating
|
* Create inclusive destructor for struct/class by aggregating
|
||||||
* all the destructors in dtors[] with the destructors for
|
* 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
|
Loc loc = Loc(); // internal code should have no loc to prevent coverage
|
||||||
|
|
||||||
Expression *e = NULL;
|
Expression *e = NULL;
|
||||||
#if DMDV2
|
|
||||||
for (size_t i = 0; i < fields.dim; i++)
|
for (size_t i = 0; i < fields.dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = fields[i];
|
Dsymbol *s = fields[i];
|
||||||
@@ -946,7 +948,6 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
|||||||
members->push(dd);
|
members->push(dd);
|
||||||
dd->semantic(sc);
|
dd->semantic(sc);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (dtors.dim)
|
switch (dtors.dim)
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-4
@@ -34,11 +34,11 @@ int findCondition(Strings *ids, Identifier *ident)
|
|||||||
const char *id = (*ids)[i];
|
const char *id = (*ids)[i];
|
||||||
|
|
||||||
if (strcmp(id, ident->toChars()) == 0)
|
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;
|
goto Lerror;
|
||||||
}
|
}
|
||||||
else if (e->isBool(TRUE))
|
else if (e->isBool(true))
|
||||||
inc = 1;
|
inc = 1;
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
inc = 2;
|
inc = 2;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+30
-123
@@ -14,10 +14,6 @@
|
|||||||
#include <string.h> // mem{cpy|set|cmp}()
|
#include <string.h> // mem{cpy|set|cmp}()
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#if __DMC__
|
|
||||||
#include <complex.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
@@ -185,17 +181,6 @@ Expression *Add(Type *type, Expression *e1, Expression *e2)
|
|||||||
|
|
||||||
switch (x)
|
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+0: v = complex_t(r1 + r2, 0); break;
|
||||||
case 0+1: v = complex_t(r1, i2); break;
|
case 0+1: v = complex_t(r1, i2); break;
|
||||||
case 0+2: v = complex_t(r1 + creall(c2), cimagl(c2)); 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+0: v = complex_t(creall(c1) + r2, cimagl(c2)); break;
|
||||||
case 6+1: v = complex_t(creall(c1), cimagl(c1) + i2); break;
|
case 6+1: v = complex_t(creall(c1), cimagl(c1) + i2); break;
|
||||||
case 6+2: v = c1 + c2; break;
|
case 6+2: v = c1 + c2; break;
|
||||||
#endif
|
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
e = new ComplexExp(loc, v, type);
|
e = new ComplexExp(loc, v, type);
|
||||||
@@ -282,17 +266,6 @@ Expression *Min(Type *type, Expression *e1, Expression *e2)
|
|||||||
|
|
||||||
switch (x)
|
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+0: v = complex_t(r1 - r2, 0); break;
|
||||||
case 0+1: v = complex_t(r1, -i2); break;
|
case 0+1: v = complex_t(r1, -i2); break;
|
||||||
case 0+2: v = complex_t(r1 - creall(c2), -cimagl(c2)); 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+0: v = complex_t(creall(c1) - r2, cimagl(c1)); break;
|
||||||
case 6+1: v = complex_t(creall(c1), cimagl(c1) - i2); break;
|
case 6+1: v = complex_t(creall(c1), cimagl(c1) - i2); break;
|
||||||
case 6+2: v = c1 - c2; break;
|
case 6+2: v = c1 - c2; break;
|
||||||
#endif
|
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
e = new ComplexExp(loc, v, type);
|
e = new ComplexExp(loc, v, type);
|
||||||
@@ -330,43 +302,27 @@ Expression *Mul(Type *type, Expression *e1, Expression *e2)
|
|||||||
|
|
||||||
if (e1->type->isreal())
|
if (e1->type->isreal())
|
||||||
{
|
{
|
||||||
#if __DMC__
|
|
||||||
c = e1->toReal() * e2->toComplex();
|
|
||||||
#else
|
|
||||||
r = e1->toReal();
|
r = e1->toReal();
|
||||||
c = e2->toComplex();
|
c = e2->toComplex();
|
||||||
c = complex_t(r * creall(c), r * cimagl(c));
|
c = complex_t(r * creall(c), r * cimagl(c));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e1->type->isimaginary())
|
else if (e1->type->isimaginary())
|
||||||
{
|
{
|
||||||
#if __DMC__
|
|
||||||
c = e1->toImaginary() * I * e2->toComplex();
|
|
||||||
#else
|
|
||||||
r = e1->toImaginary();
|
r = e1->toImaginary();
|
||||||
c = e2->toComplex();
|
c = e2->toComplex();
|
||||||
c = complex_t(-r * cimagl(c), r * creall(c));
|
c = complex_t(-r * cimagl(c), r * creall(c));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e2->type->isreal())
|
else if (e2->type->isreal())
|
||||||
{
|
{
|
||||||
#if __DMC__
|
|
||||||
c = e2->toReal() * e1->toComplex();
|
|
||||||
#else
|
|
||||||
r = e2->toReal();
|
r = e2->toReal();
|
||||||
c = e1->toComplex();
|
c = e1->toComplex();
|
||||||
c = complex_t(r * creall(c), r * cimagl(c));
|
c = complex_t(r * creall(c), r * cimagl(c));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e2->type->isimaginary())
|
else if (e2->type->isimaginary())
|
||||||
{
|
{
|
||||||
#if __DMC__
|
|
||||||
c = e1->toComplex() * e2->toImaginary() * I;
|
|
||||||
#else
|
|
||||||
r = e2->toImaginary();
|
r = e2->toImaginary();
|
||||||
c = e1->toComplex();
|
c = e1->toComplex();
|
||||||
c = complex_t(-r * cimagl(c), r * creall(c));
|
c = complex_t(-r * cimagl(c), r * creall(c));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
c = e1->toComplex() * e2->toComplex();
|
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);
|
e = new RealExp(loc, e1->toReal() / e2->toReal(), type);
|
||||||
return e;
|
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();
|
r = e2->toReal();
|
||||||
c = e1->toComplex();
|
c = e1->toComplex();
|
||||||
c = complex_t(creall(c) / r, cimagl(c) / r);
|
c = complex_t(creall(c) / r, cimagl(c) / r);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e2->type->isimaginary())
|
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();
|
r = e2->toImaginary();
|
||||||
c = e1->toComplex();
|
c = e1->toComplex();
|
||||||
c = complex_t(cimagl(c) / r, -creall(c) / r);
|
c = complex_t(cimagl(c) / r, -creall(c) / r);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -476,20 +416,12 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
|
|||||||
if (e2->type->isreal())
|
if (e2->type->isreal())
|
||||||
{ real_t r2 = e2->toReal();
|
{ 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));
|
c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e2->type->isimaginary())
|
else if (e2->type->isimaginary())
|
||||||
{ real_t i2 = e2->toImaginary();
|
{ 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));
|
c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -563,7 +495,12 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
|
|||||||
else
|
else
|
||||||
neg = false;
|
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);
|
r = new RealExp(loc, e1->toReal(), e1->type);
|
||||||
v = new RealExp(loc, ldouble(1.0), 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)
|
if (neg)
|
||||||
v = Div(v->type, new RealExp(loc, ldouble(1.0), v->type), v);
|
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);
|
e = new IntegerExp(loc, v->toInteger(), type);
|
||||||
else
|
else
|
||||||
e = new RealExp(loc, v->toReal(), type);
|
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);
|
Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
|
||||||
if (v == EXP_CANT_INTERPRET)
|
if (v == EXP_CANT_INTERPRET)
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
cmp = v->toInteger();
|
cmp = (int)v->toInteger();
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -885,7 +824,7 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
|
Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
|
||||||
if (v == EXP_CANT_INTERPRET)
|
if (v == EXP_CANT_INTERPRET)
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
cmp = v->toInteger();
|
cmp = (int)v->toInteger();
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -896,11 +835,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
cmp = 0;
|
cmp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0 // Should handle this
|
|
||||||
else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (e1->isConst() != 1 || e2->isConst() != 1)
|
else if (e1->isConst() != 1 || e2->isConst() != 1)
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
else if (e1->type->isreal())
|
else if (e1->type->isreal())
|
||||||
@@ -914,9 +848,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
r1 = e1->toImaginary();
|
r1 = e1->toImaginary();
|
||||||
r2 = e2->toImaginary();
|
r2 = e2->toImaginary();
|
||||||
L1:
|
L1:
|
||||||
#if __DMC__
|
|
||||||
cmp = (r1 == r2);
|
|
||||||
#else
|
|
||||||
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
|
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
|
||||||
{
|
{
|
||||||
cmp = 0;
|
cmp = 0;
|
||||||
@@ -925,7 +856,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
{
|
{
|
||||||
cmp = (r1 == r2);
|
cmp = (r1 == r2);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e1->type->iscomplex())
|
else if (e1->type->iscomplex())
|
||||||
{
|
{
|
||||||
@@ -1046,30 +976,8 @@ Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
r1 = e1->toImaginary();
|
r1 = e1->toImaginary();
|
||||||
r2 = e2->toImaginary();
|
r2 = e2->toImaginary();
|
||||||
L1:
|
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
|
// Don't rely on compiler, handle NAN arguments separately
|
||||||
|
// (DMC does do it correctly)
|
||||||
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
|
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
@@ -1114,7 +1022,6 @@ Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e1->type->iscomplex())
|
else if (e1->type->iscomplex())
|
||||||
{
|
{
|
||||||
@@ -1362,7 +1269,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
|
|||||||
}
|
}
|
||||||
else if (e1->op == TOKarrayliteral)
|
else if (e1->op == TOKarrayliteral)
|
||||||
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
|
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
|
||||||
e = (*ale->elements)[i];
|
e = (*ale->elements)[(size_t)i];
|
||||||
e->type = type;
|
e->type = type;
|
||||||
e->loc = loc;
|
e->loc = loc;
|
||||||
if (e->hasSideEffect())
|
if (e->hasSideEffect())
|
||||||
@@ -1381,7 +1288,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
|
|||||||
e = new ErrorExp();
|
e = new ErrorExp();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ e = (*ale->elements)[i];
|
{ e = (*ale->elements)[(size_t)i];
|
||||||
e->type = type;
|
e->type = type;
|
||||||
e->loc = loc;
|
e->loc = loc;
|
||||||
if (e->hasSideEffect())
|
if (e->hasSideEffect())
|
||||||
@@ -1401,7 +1308,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
|
|||||||
Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2);
|
Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2);
|
||||||
if (ex == EXP_CANT_INTERPRET)
|
if (ex == EXP_CANT_INTERPRET)
|
||||||
return ex;
|
return ex;
|
||||||
if (ex->isBool(TRUE))
|
if (ex->isBool(true))
|
||||||
{ e = (*ae->values)[i];
|
{ e = (*ae->values)[i];
|
||||||
e->type = type;
|
e->type = type;
|
||||||
e->loc = loc;
|
e->loc = loc;
|
||||||
@@ -1441,8 +1348,8 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
void *s;
|
void *s;
|
||||||
size_t len = iupr - ilwr;
|
size_t len = (size_t)(iupr - ilwr);
|
||||||
int sz = es1->sz;
|
unsigned char sz = es1->sz;
|
||||||
StringExp *es;
|
StringExp *es;
|
||||||
|
|
||||||
s = mem.malloc((len + 1) * sz);
|
s = mem.malloc((len + 1) * sz);
|
||||||
@@ -1471,10 +1378,10 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Expressions *elements = new Expressions();
|
Expressions *elements = new Expressions();
|
||||||
elements->setDim(iupr - ilwr);
|
elements->setDim((size_t)(iupr - ilwr));
|
||||||
memcpy(elements->tdata(),
|
memcpy(elements->tdata(),
|
||||||
es1->elements->tdata() + ilwr,
|
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 = new ArrayLiteralExp(e1->loc, elements);
|
||||||
e->type = type;
|
e->type = type;
|
||||||
}
|
}
|
||||||
@@ -1519,8 +1426,8 @@ void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *n
|
|||||||
unsigned value = (unsigned)((*newae->elements)[j]->toInteger());
|
unsigned value = (unsigned)((*newae->elements)[j]->toInteger());
|
||||||
switch (existingSE->sz)
|
switch (existingSE->sz)
|
||||||
{
|
{
|
||||||
case 1: s[j+firstIndex] = value; break;
|
case 1: s[j+firstIndex] = (utf8_t)value; break;
|
||||||
case 2: ((unsigned short *)s)[j+firstIndex] = value; break;
|
case 2: ((unsigned short *)s)[j+firstIndex] = (unsigned short)value; break;
|
||||||
case 4: ((unsigned *)s)[j+firstIndex] = value; break;
|
case 4: ((unsigned *)s)[j+firstIndex] = value; break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -1609,11 +1516,11 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||||||
StringExp *es;
|
StringExp *es;
|
||||||
if (t->nextOf())
|
if (t->nextOf())
|
||||||
t = t->nextOf()->toBasetype();
|
t = t->nextOf()->toBasetype();
|
||||||
size_t sz = t->size();
|
unsigned char sz = (unsigned char)t->size();
|
||||||
|
|
||||||
dinteger_t v = e->toInteger();
|
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);
|
s = mem.malloc((len + 1) * sz);
|
||||||
if (t->ty == tn->ty)
|
if (t->ty == tn->ty)
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
@@ -1627,7 +1534,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||||||
memcpy((utf8_t *)s, &v, sz);
|
memcpy((utf8_t *)s, &v, sz);
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
utf_encode(sz, s, v);
|
utf_encode(sz, s, (dchar_t)v);
|
||||||
|
|
||||||
// Add terminating 0
|
// Add terminating 0
|
||||||
memset((utf8_t *)s + len * sz, 0, sz);
|
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 *es2 = (StringExp *)e2;
|
||||||
StringExp *es;
|
StringExp *es;
|
||||||
size_t len = es1->len + es2->len;
|
size_t len = es1->len + es2->len;
|
||||||
int sz = es1->sz;
|
unsigned char sz = es1->sz;
|
||||||
|
|
||||||
if (sz != es2->sz)
|
if (sz != es2->sz)
|
||||||
{
|
{
|
||||||
@@ -1737,14 +1644,14 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||||||
void *s;
|
void *s;
|
||||||
StringExp *es1 = (StringExp *)e1;
|
StringExp *es1 = (StringExp *)e1;
|
||||||
StringExp *es;
|
StringExp *es;
|
||||||
size_t sz = es1->sz;
|
unsigned char sz = es1->sz;
|
||||||
dinteger_t v = e2->toInteger();
|
dinteger_t v = e2->toInteger();
|
||||||
|
|
||||||
// Is it a concatentation of homogenous types?
|
// Is it a concatentation of homogenous types?
|
||||||
// (char[] ~ char, wchar[]~wchar, or dchar[]~dchar)
|
// (char[] ~ char, wchar[]~wchar, or dchar[]~dchar)
|
||||||
bool homoConcat = (sz == t2->size());
|
bool homoConcat = (sz == t2->size());
|
||||||
size_t len = es1->len;
|
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);
|
s = mem.malloc((len + 1) * sz);
|
||||||
memcpy(s, es1->string, es1->len * 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);
|
memcpy((utf8_t *)s + (sz * es1->len), &v, sz);
|
||||||
#endif
|
#endif
|
||||||
else
|
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
|
// Add terminating 0
|
||||||
memset((utf8_t *)s + len * sz, 0, sz);
|
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 *es2 = (StringExp *)e2;
|
||||||
StringExp *es;
|
StringExp *es;
|
||||||
size_t len = 1 + es2->len;
|
size_t len = 1 + es2->len;
|
||||||
int sz = es2->sz;
|
unsigned char sz = es2->sz;
|
||||||
dinteger_t v = e1->toInteger();
|
dinteger_t v = e1->toInteger();
|
||||||
|
|
||||||
s = mem.malloc((len + 1) * sz);
|
s = mem.malloc((len + 1) * sz);
|
||||||
@@ -1917,7 +1824,7 @@ Expression *Ptr(Type *type, Expression *e1)
|
|||||||
{ AddrExp *ade = (AddrExp *)ae->e1;
|
{ AddrExp *ade = (AddrExp *)ae->e1;
|
||||||
if (ade->e1->op == TOKstructliteral)
|
if (ade->e1->op == TOKstructliteral)
|
||||||
{ StructLiteralExp *se = (StructLiteralExp *)ade->e1;
|
{ StructLiteralExp *se = (StructLiteralExp *)ade->e1;
|
||||||
unsigned offset = ae->e2->toInteger();
|
unsigned offset = (unsigned)ae->e2->toInteger();
|
||||||
Expression *e = se->getField(type, offset);
|
Expression *e = se->getField(type, offset);
|
||||||
if (!e)
|
if (!e)
|
||||||
e = EXP_CANT_INTERPRET;
|
e = EXP_CANT_INTERPRET;
|
||||||
|
|||||||
+1
-1
@@ -127,7 +127,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
|
|||||||
|
|
||||||
/// Create a string literal consisting of 'value' duplicated 'dim' times.
|
/// Create a string literal consisting of 'value' duplicated 'dim' times.
|
||||||
StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
|
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
|
/* Set dest = src, where both dest and src are container value literals
|
||||||
|
|||||||
+69
-52
@@ -314,12 +314,13 @@ Expression *copyLiteral(Expression *e)
|
|||||||
}
|
}
|
||||||
else if (e->op == TOKfunction || e->op == TOKdelegate
|
else if (e->op == TOKfunction || e->op == TOKdelegate
|
||||||
|| e->op == TOKsymoff || e->op == TOKnull
|
|| e->op == TOKsymoff || e->op == TOKnull
|
||||||
|| e->op == TOKvar
|
|| e->op == TOKvar || e->op == TOKdotvar
|
||||||
|| e->op == TOKint64 || e->op == TOKfloat64
|
|| e->op == TOKint64 || e->op == TOKfloat64
|
||||||
|| e->op == TOKchar || e->op == TOKcomplex80
|
|| e->op == TOKchar || e->op == TOKcomplex80
|
||||||
|| e->op == TOKvoid)
|
|| 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;
|
r->type = e->type;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -331,12 +332,14 @@ Expression *copyLiteral(Expression *e)
|
|||||||
else if (e->op == TOKindex)
|
else if (e->op == TOKindex)
|
||||||
r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2);
|
r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2);
|
||||||
else if (e->op == TOKdotvar)
|
else if (e->op == TOKdotvar)
|
||||||
|
{
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1,
|
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1,
|
||||||
((DotVarExp *)e)->var, ((DotVarExp *)e)->hasOverloads);
|
((DotVarExp *)e)->var, ((DotVarExp *)e)->hasOverloads);
|
||||||
#else
|
#else
|
||||||
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var);
|
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
r->type = e->type;
|
r->type = e->type;
|
||||||
@@ -470,7 +473,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
|
|||||||
{
|
{
|
||||||
// If it is a multidimensional array literal, do it recursively
|
// If it is a multidimensional array literal, do it recursively
|
||||||
elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem,
|
elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem,
|
||||||
((TypeSArray *)type->nextOf())->dim->toInteger());
|
(size_t)((TypeSArray *)type->nextOf())->dim->toInteger());
|
||||||
}
|
}
|
||||||
bool mustCopy = needToCopyLiteral(elem);
|
bool mustCopy = needToCopyLiteral(elem);
|
||||||
for (size_t i = 0; i < dim; i++)
|
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.
|
* Create a string literal consisting of 'value' duplicated 'dim' times.
|
||||||
*/
|
*/
|
||||||
StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
|
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);
|
utf8_t *s = (utf8_t *)mem.calloc(dim + 1, sz);
|
||||||
for (size_t elemi = 0; elemi < dim; ++elemi)
|
for (size_t elemi = 0; elemi < dim; ++elemi)
|
||||||
{
|
{
|
||||||
switch (sz)
|
switch (sz)
|
||||||
{
|
{
|
||||||
case 1: s[elemi] = value; break;
|
case 1: s[elemi] = (utf8_t)value; break;
|
||||||
case 2: ((unsigned short *)s)[elemi] = value; break;
|
case 2: ((unsigned short *)s)[elemi] = (unsigned short)value; break;
|
||||||
case 4: ((unsigned *)s)[elemi] = value; break;
|
case 4: ((unsigned *)s)[elemi] = value; break;
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
@@ -568,10 +571,10 @@ bool isPointer(Type *t)
|
|||||||
return tb->ty == Tpointer && tb->nextOf()->ty != Tfunction;
|
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)
|
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);
|
&& e->op != TOKnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,7 +789,7 @@ int comparePointers(Loc loc, TOK op, Type *type, Expression *agg1, dinteger_t of
|
|||||||
{
|
{
|
||||||
if ( pointToSameMemoryBlock(agg1, agg2) )
|
if ( pointToSameMemoryBlock(agg1, agg2) )
|
||||||
{
|
{
|
||||||
dinteger_t n;
|
int n;
|
||||||
switch(op)
|
switch(op)
|
||||||
{
|
{
|
||||||
case TOKlt: n = (ofs1 < ofs2); break;
|
case TOKlt: n = (ofs1 < ofs2); break;
|
||||||
@@ -880,7 +883,7 @@ Expression *paintFloatInt(Expression *fromVal, Type *to)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u.x = fromVal->toInteger();
|
u.x = (d_int32)fromVal->toInteger();
|
||||||
return new RealExp(fromVal->loc, ldouble(u.f), to);
|
return new RealExp(fromVal->loc, ldouble(u.f), to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1128,6 +1131,7 @@ bool isCtfeComparable(Expression *e)
|
|||||||
x->op != TOKdelegate &&
|
x->op != TOKdelegate &&
|
||||||
x->op != TOKarrayliteral &&
|
x->op != TOKarrayliteral &&
|
||||||
x->op != TOKstructliteral &&
|
x->op != TOKstructliteral &&
|
||||||
|
x->op != TOKassocarrayliteral &&
|
||||||
x->op != TOKclassreference)
|
x->op != TOKclassreference)
|
||||||
{
|
{
|
||||||
return false;
|
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 realCmp(TOK op, real_t r1, real_t r2)
|
||||||
{
|
{
|
||||||
int n;
|
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
|
// Don't rely on compiler, handle NAN arguments separately
|
||||||
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
|
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);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return n;
|
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
|
// Now both must be either TOKarrayliteral or TOKstring
|
||||||
if (se1 && se2)
|
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)
|
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)
|
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);
|
assert (ae1 && ae2);
|
||||||
// Comparing two array literals. This case is potentially recursive.
|
// 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.
|
// a full cmp.
|
||||||
bool needCmp = ae1->type->nextOf()->isintegral();
|
bool needCmp = ae1->type->nextOf()->isintegral();
|
||||||
for (size_t i = 0; i < len; i++)
|
for (size_t i = 0; i < len; i++)
|
||||||
{ Expression *ee1 = (*ae1->elements)[lo1 + i];
|
{ Expression *ee1 = (*ae1->elements)[(size_t)(lo1 + i)];
|
||||||
Expression *ee2 = (*ae2->elements)[lo2 + i];
|
Expression *ee2 = (*ae2->elements)[(size_t)(lo2 + i)];
|
||||||
if (needCmp)
|
if (needCmp)
|
||||||
{ sinteger_t c = ee1->toInteger() - ee2->toInteger();
|
{ sinteger_t c = ee1->toInteger() - ee2->toInteger();
|
||||||
if (c > 0)
|
if (c > 0)
|
||||||
@@ -1418,7 +1399,7 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
|
|||||||
if (res != 0)
|
if (res != 0)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
return len1 - len2;
|
return (int)(len1 - len2);
|
||||||
}
|
}
|
||||||
if (e1->type->isintegral())
|
if (e1->type->isintegral())
|
||||||
{
|
{
|
||||||
@@ -1437,9 +1418,6 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
|
|||||||
r1 = e1->toImaginary();
|
r1 = e1->toImaginary();
|
||||||
r2 = e2->toImaginary();
|
r2 = e2->toImaginary();
|
||||||
L1:
|
L1:
|
||||||
#if __DMC__
|
|
||||||
return (r1 != r2);
|
|
||||||
#else
|
|
||||||
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
|
if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1448,7 +1426,6 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
|
|||||||
{
|
{
|
||||||
return (r1 != r2);
|
return (r1 != r2);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else if (e1->type->iscomplex())
|
else if (e1->type->iscomplex())
|
||||||
{
|
{
|
||||||
@@ -1486,6 +1463,43 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
|
|||||||
return 0; // All elements are equal
|
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");
|
error(loc, "CTFE internal error: bad compare");
|
||||||
assert(0);
|
assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1601,7 +1615,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
|||||||
StringExp *es1 = (StringExp *)e2;
|
StringExp *es1 = (StringExp *)e2;
|
||||||
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1;
|
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1;
|
||||||
size_t len = es1->len + es2->elements->dim;
|
size_t len = es1->len + es2->elements->dim;
|
||||||
int sz = es1->sz;
|
unsigned char sz = es1->sz;
|
||||||
|
|
||||||
void *s = mem.malloc((len + 1) * sz);
|
void *s = mem.malloc((len + 1) * sz);
|
||||||
memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * 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;
|
StringExp *es1 = (StringExp *)e1;
|
||||||
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
|
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
|
||||||
size_t len = es1->len + es2->elements->dim;
|
size_t len = es1->len + es2->elements->dim;
|
||||||
int sz = es1->sz;
|
unsigned char sz = es1->sz;
|
||||||
|
|
||||||
void *s = mem.malloc((len + 1) * sz);
|
void *s = mem.malloc((len + 1) * sz);
|
||||||
memcpy(s, es1->string, es1->len * 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);
|
error(loc, "array index %llu is out of bounds %s[0 .. %llu]", indx, e1->toChars(), (ulonglong)ale->elements->dim);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
Expression *e = (*ale->elements)[indx];
|
Expression *e = (*ale->elements)[(size_t)indx];
|
||||||
return paintTypeOntoLiteral(type, e);
|
return paintTypeOntoLiteral(type, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1949,7 +1963,7 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
|
|||||||
// Resolve slices
|
// Resolve slices
|
||||||
size_t indxlo = 0;
|
size_t indxlo = 0;
|
||||||
if (oldval->op == TOKslice)
|
if (oldval->op == TOKslice)
|
||||||
{ indxlo = ((SliceExp *)oldval)->lwr->toInteger();
|
{ indxlo = (size_t)((SliceExp *)oldval)->lwr->toInteger();
|
||||||
oldval = ((SliceExp *)oldval)->e1;
|
oldval = ((SliceExp *)oldval)->e1;
|
||||||
}
|
}
|
||||||
size_t copylen = oldlen < newlen ? oldlen : newlen;
|
size_t copylen = oldlen < newlen ? oldlen : newlen;
|
||||||
@@ -1963,9 +1977,9 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
|
|||||||
{
|
{
|
||||||
switch (oldse->sz)
|
switch (oldse->sz)
|
||||||
{
|
{
|
||||||
case 1: s[indxlo + elemi] = defaultValue; break;
|
case 1: s[(size_t)(indxlo + elemi)] = (utf8_t)defaultValue; break;
|
||||||
case 2: ((unsigned short *)s)[indxlo + elemi] = defaultValue; break;
|
case 2: ((unsigned short *)s)[(size_t)(indxlo + elemi)] = (unsigned short)defaultValue; break;
|
||||||
case 4: ((unsigned *)s)[indxlo + elemi] = defaultValue; break;
|
case 4: ((unsigned *)s)[(size_t)(indxlo + elemi)] = defaultValue; break;
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2069,6 +2083,9 @@ bool isCtfeValueValid(Expression *newval)
|
|||||||
if (newval->op == TOKfunction)
|
if (newval->op == TOKfunction)
|
||||||
return true; // function literal or delegate literal
|
return true; // function literal or delegate literal
|
||||||
|
|
||||||
|
if (newval->op == TOKvector)
|
||||||
|
return true; // vector literal
|
||||||
|
|
||||||
if (newval->op == TOKdelegate)
|
if (newval->op == TOKdelegate)
|
||||||
{
|
{
|
||||||
Expression *dge = ((DelegateExp *)newval)->e1;
|
Expression *dge = ((DelegateExp *)newval)->e1;
|
||||||
@@ -2254,7 +2271,7 @@ Expression *TypeSArray::voidInitLiteral(VarDeclaration *var)
|
|||||||
bool mustCopy = (elem->op == TOKarrayliteral || elem->op == TOKstructliteral);
|
bool mustCopy = (elem->op == TOKarrayliteral || elem->op == TOKstructliteral);
|
||||||
|
|
||||||
Expressions *elements = new Expressions();
|
Expressions *elements = new Expressions();
|
||||||
size_t d = dim->toInteger();
|
size_t d = (size_t)dim->toInteger();
|
||||||
elements->setDim(d);
|
elements->setDim(d);
|
||||||
for (size_t i = 0; i < d; i++)
|
for (size_t i = 0; i < d; i++)
|
||||||
{ if (mustCopy && i > 0)
|
{ if (mustCopy && i > 0)
|
||||||
|
|||||||
+72
-265
@@ -27,8 +27,6 @@
|
|||||||
#include "ctfe.h"
|
#include "ctfe.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
|
||||||
AggregateDeclaration *isAggregate(Type *t); // from opover.c
|
|
||||||
|
|
||||||
void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad)
|
void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad)
|
||||||
{
|
{
|
||||||
if (!ad->isNested())
|
if (!ad->isNested())
|
||||||
@@ -99,7 +97,7 @@ const char *Declaration::kind()
|
|||||||
unsigned Declaration::size(Loc loc)
|
unsigned Declaration::size(Loc loc)
|
||||||
{
|
{
|
||||||
assert(type);
|
assert(type);
|
||||||
return type->size();
|
return (unsigned)type->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Declaration::isDelete()
|
bool Declaration::isDelete()
|
||||||
@@ -132,8 +130,6 @@ PROT Declaration::prot()
|
|||||||
* Issue error if not.
|
* Issue error if not.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
|
|
||||||
int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag)
|
int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag)
|
||||||
{
|
{
|
||||||
VarDeclaration *v = isVarDeclaration();
|
VarDeclaration *v = isVarDeclaration();
|
||||||
@@ -161,14 +157,13 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int fl
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Dsymbol *Declaration::search(Loc loc, Identifier *ident, int flags)
|
Dsymbol *Declaration::search(Loc loc, Identifier *ident, int flags)
|
||||||
{
|
{
|
||||||
Dsymbol *s = Dsymbol::search(loc, ident, flags);
|
Dsymbol *s = Dsymbol::search(loc, ident, flags);
|
||||||
if (!s && type)
|
if (!s && type)
|
||||||
{
|
{
|
||||||
s = type->toDsymbol(NULL);
|
s = type->toDsymbol(scope);
|
||||||
if (s)
|
if (s)
|
||||||
s = s->search(loc, ident, flags);
|
s = s->search(loc, ident, flags);
|
||||||
}
|
}
|
||||||
@@ -359,9 +354,7 @@ void TypedefDeclaration::semantic(Scope *sc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sem = SemanticDone;
|
sem = SemanticDone;
|
||||||
#if DMDV2
|
|
||||||
type = type->addStorageClass(storage_class);
|
type = type->addStorageClass(storage_class);
|
||||||
#endif
|
|
||||||
Type *savedtype = type;
|
Type *savedtype = type;
|
||||||
type = type->semantic(loc, sc);
|
type = type->semantic(loc, sc);
|
||||||
if (sc->parent->isFuncDeclaration() && init)
|
if (sc->parent->isFuncDeclaration() && init)
|
||||||
@@ -379,6 +372,8 @@ void TypedefDeclaration::semantic(Scope *sc)
|
|||||||
else if (sem == SemanticIn)
|
else if (sem == SemanticIn)
|
||||||
{
|
{
|
||||||
error("circular definition");
|
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);
|
//printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
|
||||||
if (sem == SemanticDone)
|
if (sem == SemanticDone)
|
||||||
{ sem = Semantic2Done;
|
{ sem = Semantic2Done;
|
||||||
|
basetype->alignment(); // used to detect circular typedef declarations
|
||||||
if (init)
|
if (init)
|
||||||
{
|
{
|
||||||
Initializer *savedinit = init;
|
Initializer *savedinit = init;
|
||||||
@@ -508,11 +504,6 @@ void AliasDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
this->inSemantic = true;
|
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;
|
storage_class |= sc->stc & STCdeprecated;
|
||||||
protection = sc->protection;
|
protection = sc->protection;
|
||||||
userAttributes = sc->userAttributes;
|
userAttributes = sc->userAttributes;
|
||||||
@@ -545,14 +536,9 @@ void AliasDeclaration::semantic(Scope *sc)
|
|||||||
s = NULL;
|
s = NULL;
|
||||||
type = Type::terror;
|
type = Type::terror;
|
||||||
}
|
}
|
||||||
if (s
|
if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()))
|
||||||
#if DMDV2
|
|
||||||
&& ((s->getType() && type->equals(s->getType())) || s->isEnumMember())
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
goto L2; // it's a symbolic alias
|
goto L2; // it's a symbolic alias
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
type = type->addStorageClass(storage_class);
|
type = type->addStorageClass(storage_class);
|
||||||
if (storage_class & (STCref | STCnothrow | STCpure | STCdisable))
|
if (storage_class & (STCref | STCnothrow | STCpure | STCdisable))
|
||||||
{ // For 'ref' to be attached to function types, and picked
|
{ // For 'ref' to be attached to function types, and picked
|
||||||
@@ -563,7 +549,6 @@ void AliasDeclaration::semantic(Scope *sc)
|
|||||||
sc = sc->pop();
|
sc = sc->pop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
type->resolve(loc, sc, &e, &t, &s);
|
type->resolve(loc, sc, &e, &t, &s);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
@@ -730,38 +715,18 @@ Dsymbol *AliasDeclaration::toAlias()
|
|||||||
void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||||
{
|
{
|
||||||
buf->writestring("alias ");
|
buf->writestring("alias ");
|
||||||
#if 0
|
if (aliassym)
|
||||||
if (hgs->hdrgen)
|
|
||||||
{
|
{
|
||||||
if (haliassym)
|
|
||||||
{
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
buf->writestring(haliassym->toChars());
|
buf->writestring(aliassym->toChars());
|
||||||
#else
|
#else
|
||||||
haliassym->toCBuffer(buf, hgs);
|
aliassym->toCBuffer(buf, hgs);
|
||||||
#endif
|
#endif
|
||||||
buf->writeByte(' ');
|
buf->writeByte(' ');
|
||||||
buf->writestring(ident->toChars());
|
buf->writestring(ident->toChars());
|
||||||
}
|
|
||||||
else
|
|
||||||
htype->toCBuffer(buf, ident, hgs);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
type->toCBuffer(buf, ident, hgs);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
buf->writeByte(';');
|
buf->writeByte(';');
|
||||||
buf->writenl();
|
buf->writenl();
|
||||||
}
|
}
|
||||||
@@ -786,27 +751,19 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
|
|||||||
this->loc = loc;
|
this->loc = loc;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
noscope = 0;
|
noscope = 0;
|
||||||
#if DMDV2
|
isargptr = false;
|
||||||
isargptr = FALSE;
|
|
||||||
#endif
|
|
||||||
#if DMDV1
|
|
||||||
nestedref = 0;
|
|
||||||
#endif
|
|
||||||
alignment = 0;
|
alignment = 0;
|
||||||
ctorinit = 0;
|
ctorinit = 0;
|
||||||
aliassym = NULL;
|
aliassym = NULL;
|
||||||
onstack = 0;
|
onstack = 0;
|
||||||
canassign = 0;
|
canassign = 0;
|
||||||
|
lastVar = NULL;
|
||||||
ctfeAdrOnStack = -1;
|
ctfeAdrOnStack = -1;
|
||||||
#if DMDV2
|
|
||||||
rundtor = NULL;
|
rundtor = NULL;
|
||||||
edtor = NULL;
|
edtor = NULL;
|
||||||
#endif
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
aggrIndex = 0;
|
aggrIndex = 0;
|
||||||
|
|
||||||
nakedUse = false;
|
nakedUse = false;
|
||||||
|
|
||||||
availableExternally = true; // assume this unless proven otherwise
|
availableExternally = true; // assume this unless proven otherwise
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -873,7 +830,8 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
Scope *scx = NULL;
|
Scope *scx = NULL;
|
||||||
if (scope)
|
if (scope)
|
||||||
{ sc = scope;
|
{
|
||||||
|
sc = scope;
|
||||||
scx = sc;
|
scx = sc;
|
||||||
scope = NULL;
|
scope = NULL;
|
||||||
}
|
}
|
||||||
@@ -894,17 +852,19 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
*/
|
*/
|
||||||
int inferred = 0;
|
int inferred = 0;
|
||||||
if (!type)
|
if (!type)
|
||||||
{ inuse++;
|
{
|
||||||
|
inuse++;
|
||||||
|
|
||||||
// Infering the type requires running semantic,
|
// Infering the type requires running semantic,
|
||||||
// so mark the scope as ctfe if required
|
// 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();
|
if (needctfe) sc = sc->startCTFE();
|
||||||
|
|
||||||
//printf("inferring type for %s with init %s\n", toChars(), init->toChars());
|
//printf("inferring type for %s with init %s\n", toChars(), init->toChars());
|
||||||
ArrayInitializer *ai = init->isArrayInitializer();
|
ArrayInitializer *ai = init->isArrayInitializer();
|
||||||
if (ai)
|
if (ai)
|
||||||
{ Expression *e;
|
{
|
||||||
|
Expression *e;
|
||||||
if (ai->isAssociativeArray())
|
if (ai->isAssociativeArray())
|
||||||
e = ai->toAssocArrayLiteral();
|
e = ai->toAssocArrayLiteral();
|
||||||
else
|
else
|
||||||
@@ -931,7 +891,8 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
inferred = 1;
|
inferred = 1;
|
||||||
|
|
||||||
if (init->isArrayInitializer() && type->toBasetype()->ty == Tsarray)
|
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();
|
type = type->toBasetype()->nextOf()->arrayOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,7 +903,8 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
originalType = type->syntaxCopy();
|
originalType = type->syntaxCopy();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ if (!originalType)
|
{
|
||||||
|
if (!originalType)
|
||||||
originalType = type->syntaxCopy();
|
originalType = type->syntaxCopy();
|
||||||
inuse++;
|
inuse++;
|
||||||
type = type->semantic(loc, sc);
|
type = type->semantic(loc, sc);
|
||||||
@@ -966,7 +928,6 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
//printf("sc->stc = %x\n", sc->stc);
|
//printf("sc->stc = %x\n", sc->stc);
|
||||||
//printf("storage_class = x%x\n", storage_class);
|
//printf("storage_class = x%x\n", storage_class);
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
// Safety checks
|
// Safety checks
|
||||||
if (sc->func && !sc->intypeof)
|
if (sc->func && !sc->intypeof)
|
||||||
{
|
{
|
||||||
@@ -994,10 +955,8 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Dsymbol *parent = toParent();
|
Dsymbol *parent = toParent();
|
||||||
FuncDeclaration *fd = parent->isFuncDeclaration();
|
|
||||||
|
|
||||||
Type *tb = type->toBasetype();
|
Type *tb = type->toBasetype();
|
||||||
Type *tbn = tb->baseElemOf();
|
Type *tbn = tb->baseElemOf();
|
||||||
@@ -1014,13 +973,14 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
tb = type;
|
tb = type;
|
||||||
}
|
}
|
||||||
if (tb->ty == Tfunction)
|
if (tb->ty == Tfunction)
|
||||||
{ error("cannot be declared to be a function");
|
{
|
||||||
|
error("cannot be declared to be a function");
|
||||||
type = Type::terror;
|
type = Type::terror;
|
||||||
tb = type;
|
tb = type;
|
||||||
}
|
}
|
||||||
if (tb->ty == Tstruct)
|
if (tb->ty == Tstruct)
|
||||||
{ TypeStruct *ts = (TypeStruct *)tb;
|
{
|
||||||
|
TypeStruct *ts = (TypeStruct *)tb;
|
||||||
if (!ts->sym->members)
|
if (!ts->sym->members)
|
||||||
{
|
{
|
||||||
error("no definition of struct %s", ts->toChars());
|
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'?");
|
error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?");
|
||||||
|
|
||||||
if (tb->ty == Ttuple)
|
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.
|
* and add those.
|
||||||
*/
|
*/
|
||||||
TypeTuple *tt = (TypeTuple *)tb;
|
TypeTuple *tt = (TypeTuple *)tb;
|
||||||
size_t nelems = Parameter::dim(tt->arguments);
|
size_t nelems = Parameter::dim(tt->arguments);
|
||||||
Objects *exps = new Objects();
|
|
||||||
exps->setDim(nelems);
|
|
||||||
Expression *ie = (init && !init->isVoidInitializer()) ? init->toExpression() : NULL;
|
Expression *ie = (init && !init->isVoidInitializer()) ? init->toExpression() : NULL;
|
||||||
if (ie) ie = ie->semantic(sc);
|
if (ie) ie = ie->semantic(sc);
|
||||||
|
|
||||||
@@ -1081,7 +1040,7 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
Identifier *id = Lexer::uniqueId("__tup");
|
Identifier *id = Lexer::uniqueId("__tup");
|
||||||
ExpInitializer *ei = new ExpInitializer(e->loc, e);
|
ExpInitializer *ei = new ExpInitializer(e->loc, e);
|
||||||
VarDeclaration *v = new VarDeclaration(loc, NULL, id, ei);
|
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);
|
VarExp *ve = new VarExp(loc, v);
|
||||||
ve->type = e->type;
|
ve->type = e->type;
|
||||||
|
|
||||||
@@ -1093,7 +1052,7 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
Lexpand2:
|
Lexpand2:
|
||||||
Expression *ee = (*exps)[u];
|
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);
|
arg->type = arg->type->semantic(loc, sc);
|
||||||
//printf("[%d+%d] exps->dim = %d, ", pos, u, exps->dim);
|
//printf("[%d+%d] exps->dim = %d, ", pos, u, exps->dim);
|
||||||
//printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars());
|
//printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars());
|
||||||
@@ -1133,12 +1092,15 @@ Lnomatch:
|
|||||||
TupleExp *te = (TupleExp *)ie;
|
TupleExp *te = (TupleExp *)ie;
|
||||||
size_t tedim = te->exps->dim;
|
size_t tedim = te->exps->dim;
|
||||||
if (tedim != nelems)
|
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
|
for (size_t u = tedim; u < nelems; u++) // fill dummy expression
|
||||||
te->exps->push(new ErrorExp());
|
te->exps->push(new ErrorExp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Objects *exps = new Objects();
|
||||||
|
exps->setDim(nelems);
|
||||||
for (size_t i = 0; i < nelems; i++)
|
for (size_t i = 0; i < nelems; i++)
|
||||||
{
|
{
|
||||||
Parameter *arg = Parameter::getNth(tt->arguments, i);
|
Parameter *arg = Parameter::getNth(tt->arguments, i);
|
||||||
@@ -1166,7 +1128,7 @@ Lnomatch:
|
|||||||
ti = init ? init->syntaxCopy() : NULL;
|
ti = init ? init->syntaxCopy() : NULL;
|
||||||
|
|
||||||
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
|
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
|
||||||
v->storage_class |= storage_class;
|
v->storage_class |= STCtemp | storage_class;
|
||||||
if (arg->storageClass & STCparameter)
|
if (arg->storageClass & STCparameter)
|
||||||
v->storage_class |= arg->storageClass;
|
v->storage_class |= arg->storageClass;
|
||||||
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
|
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
|
||||||
@@ -1176,7 +1138,8 @@ Lnomatch:
|
|||||||
// removed for LDC since TupleDeclaration::toObj already creates the fields;
|
// removed for LDC since TupleDeclaration::toObj already creates the fields;
|
||||||
// adding them to the scope again leads to duplicates
|
// adding them to the scope again leads to duplicates
|
||||||
if (sc->scopesym)
|
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)
|
if (sc->scopesym->members)
|
||||||
sc->scopesym->members->push(v);
|
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);
|
fprintf(global.stdmsg, "%s: %s.%s is %s field\n", p ? p : "", ad->toPrettyChars(), toChars(), s);
|
||||||
}
|
}
|
||||||
storage_class |= STCfield;
|
storage_class |= STCfield;
|
||||||
#if DMDV2
|
|
||||||
if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor ||
|
if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor ||
|
||||||
tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor)
|
tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor)
|
||||||
{
|
{
|
||||||
if (!isThisDeclaration())
|
if (!isThisDeclaration() && !init)
|
||||||
aad->noDefaultCtor = TRUE;
|
aad->noDefaultCtor = true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
if (storage_class & (STCconst | STCimmutable) && init)
|
if (storage_class & (STCconst | STCimmutable) && init)
|
||||||
{
|
{
|
||||||
@@ -1267,14 +1228,12 @@ Lnomatch:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
storage_class |= STCfield;
|
storage_class |= STCfield;
|
||||||
#if DMDV2
|
|
||||||
if ((tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor) ||
|
if ((tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor) ||
|
||||||
(tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor))
|
(tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor))
|
||||||
{
|
{
|
||||||
if (!isThisDeclaration())
|
if (!isThisDeclaration() && !init)
|
||||||
aad->noDefaultCtor = TRUE;
|
aad->noDefaultCtor = true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1308,7 +1267,6 @@ Lnomatch:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref &&
|
if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref &&
|
||||||
ident != Id::This)
|
ident != Id::This)
|
||||||
{
|
{
|
||||||
@@ -1360,8 +1318,8 @@ Lnomatch:
|
|||||||
error("default construction is disabled for type %s", type->toChars());
|
error("default construction is disabled for type %s", type->toChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
FuncDeclaration *fd = parent->isFuncDeclaration();
|
||||||
if (type->isscope() && !noscope)
|
if (type->isscope() && !noscope)
|
||||||
{
|
{
|
||||||
if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd)
|
if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd)
|
||||||
@@ -1416,7 +1374,8 @@ Lnomatch:
|
|||||||
}
|
}
|
||||||
else if (type->ty == Tstruct &&
|
else if (type->ty == Tstruct &&
|
||||||
((TypeStruct *)type)->sym->zeroInit == 1)
|
((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.
|
* set it's initializer to the integer 0.
|
||||||
* In AssignExp::toElem(), we check for this and issue
|
* In AssignExp::toElem(), we check for this and issue
|
||||||
* a memset() to initialize the struct.
|
* a memset() to initialize the struct.
|
||||||
@@ -1431,9 +1390,11 @@ Lnomatch:
|
|||||||
goto Ldtor;
|
goto Ldtor;
|
||||||
}
|
}
|
||||||
else if (type->ty == Ttypedef)
|
else if (type->ty == Ttypedef)
|
||||||
{ TypeTypedef *td = (TypeTypedef *)type;
|
{
|
||||||
|
TypeTypedef *td = (TypeTypedef *)type;
|
||||||
if (td->sym->init)
|
if (td->sym->init)
|
||||||
{ init = td->sym->init;
|
{
|
||||||
|
init = td->sym->init;
|
||||||
ExpInitializer *ie = init->isExpInitializer();
|
ExpInitializer *ie = init->isExpInitializer();
|
||||||
if (ie)
|
if (ie)
|
||||||
// Make copy so we can modify it
|
// Make copy so we can modify it
|
||||||
@@ -1455,22 +1416,16 @@ Lnomatch:
|
|||||||
sc = sc->push();
|
sc = sc->push();
|
||||||
sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref | STCdisable);
|
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();
|
ExpInitializer *ei = init->isExpInitializer();
|
||||||
|
|
||||||
if (ei && isScope())
|
if (ei && isScope())
|
||||||
{
|
{
|
||||||
// See if initializer is a NewExp that can be allocated on the stack
|
// See if initializer is a NewExp that can be allocated on the stack
|
||||||
if (ei->exp->op == TOKnew)
|
if (ei->exp->op == TOKnew)
|
||||||
{ NewExp *ne = (NewExp *)ei->exp;
|
{
|
||||||
|
NewExp *ne = (NewExp *)ei->exp;
|
||||||
if (!(ne->newargs && ne->newargs->dim))
|
if (!(ne->newargs && ne->newargs->dim))
|
||||||
{ ne->onstack = 1;
|
{
|
||||||
|
ne->onstack = 1;
|
||||||
onstack = 1;
|
onstack = 1;
|
||||||
if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
|
if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
|
||||||
onstack = 2;
|
onstack = 2;
|
||||||
@@ -1478,7 +1433,8 @@ Lnomatch:
|
|||||||
}
|
}
|
||||||
// or a delegate that doesn't escape a reference to the function
|
// or a delegate that doesn't escape a reference to the function
|
||||||
else if (ei->exp->op == TOKfunction)
|
else if (ei->exp->op == TOKfunction)
|
||||||
{ FuncDeclaration *f = ((FuncExp *)ei->exp)->fd;
|
{
|
||||||
|
FuncDeclaration *f = ((FuncExp *)ei->exp)->fd;
|
||||||
f->tookAddressOf--;
|
f->tookAddressOf--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1495,14 +1451,20 @@ Lnomatch:
|
|||||||
//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
|
//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
|
||||||
if (!ei)
|
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)
|
if (!e)
|
||||||
{
|
{
|
||||||
// Run semantic, but don't need to interpret
|
// Run semantic, but don't need to interpret
|
||||||
init = init->semantic(sc, type, INITnointerpret);
|
init = init->semantic(sc, type, INITnointerpret);
|
||||||
e = init->toExpression();
|
e = init->toExpression();
|
||||||
if (!e)
|
if (!e)
|
||||||
{ error("is not a static and cannot have static initializer");
|
{
|
||||||
|
error("is not a static and cannot have static initializer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1511,150 +1473,6 @@ Lnomatch:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expression *e1 = new VarExp(loc, this);
|
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 = new AssignExp(loc, e1, ei->exp);
|
||||||
ei->exp->op = op;
|
ei->exp->op = op;
|
||||||
canassign++;
|
canassign++;
|
||||||
@@ -1685,7 +1503,6 @@ Lnomatch:
|
|||||||
{
|
{
|
||||||
unsigned errors = global.errors;
|
unsigned errors = global.errors;
|
||||||
inuse++;
|
inuse++;
|
||||||
#if DMDV2
|
|
||||||
if (ei)
|
if (ei)
|
||||||
{
|
{
|
||||||
Expression *exp = ei->exp->syntaxCopy();
|
Expression *exp = ei->exp->syntaxCopy();
|
||||||
@@ -1696,7 +1513,7 @@ Lnomatch:
|
|||||||
exp = resolveProperties(sc, exp);
|
exp = resolveProperties(sc, exp);
|
||||||
if (needctfe) sc = sc->endCTFE();
|
if (needctfe) sc = sc->endCTFE();
|
||||||
|
|
||||||
Type *tb = type->toBasetype();
|
Type *tb2 = type->toBasetype();
|
||||||
Type *ti = exp->type->toBasetype();
|
Type *ti = exp->type->toBasetype();
|
||||||
|
|
||||||
/* The problem is the following code:
|
/* The problem is the following code:
|
||||||
@@ -1717,16 +1534,15 @@ Lnomatch:
|
|||||||
* (which implies a postblit)
|
* (which implies a postblit)
|
||||||
*/
|
*/
|
||||||
if (sd->cpctor && // there is a copy constructor
|
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
|
// The only allowable initializer is a (non-copy) constructor
|
||||||
if (exp->isLvalue())
|
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;
|
ei->exp = exp;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
init = init->semantic(sc, type, INITinterpret);
|
init = init->semantic(sc, type, INITinterpret);
|
||||||
inuse--;
|
inuse--;
|
||||||
if (global.errors > errors)
|
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
|
unsigned memalignsize = Target::fieldalign(t); // size of member for alignment purposes
|
||||||
|
|
||||||
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment,
|
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment,
|
||||||
@@ -1978,12 +1794,10 @@ void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring(ident->toChars());
|
buf->writestring(ident->toChars());
|
||||||
if (init)
|
if (init)
|
||||||
{ buf->writestring(" = ");
|
{ buf->writestring(" = ");
|
||||||
#if DMDV2
|
|
||||||
ExpInitializer *ie = init->isExpInitializer();
|
ExpInitializer *ie = init->isExpInitializer();
|
||||||
if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
|
if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
|
||||||
((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
|
((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
init->toCBuffer(buf, hgs);
|
init->toCBuffer(buf, hgs);
|
||||||
}
|
}
|
||||||
buf->writeByte(';');
|
buf->writeByte(';');
|
||||||
@@ -2106,7 +1920,8 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
|
|||||||
{
|
{
|
||||||
if (i == fdv->closureVars.dim)
|
if (i == fdv->closureVars.dim)
|
||||||
{
|
{
|
||||||
fdv->closureVars.push(this);
|
if (!sc->intypeof && !(sc->flags & SCOPEcompile))
|
||||||
|
fdv->closureVars.push(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fdv->closureVars[i] == this)
|
if (fdv->closureVars[i] == this)
|
||||||
@@ -2440,7 +2255,6 @@ char *TypeInfoDeclaration::toChars()
|
|||||||
|
|
||||||
/***************************** TypeInfoConstDeclaration **********************/
|
/***************************** TypeInfoConstDeclaration **********************/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
|
TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
|
||||||
: TypeInfoDeclaration(tinfo, 0)
|
: TypeInfoDeclaration(tinfo, 0)
|
||||||
{
|
{
|
||||||
@@ -2450,11 +2264,9 @@ TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
|
|||||||
}
|
}
|
||||||
type = Type::typeinfoconst->type;
|
type = Type::typeinfoconst->type;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************************** TypeInfoInvariantDeclaration **********************/
|
/***************************** TypeInfoInvariantDeclaration **********************/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
|
TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
|
||||||
: TypeInfoDeclaration(tinfo, 0)
|
: TypeInfoDeclaration(tinfo, 0)
|
||||||
{
|
{
|
||||||
@@ -2464,11 +2276,9 @@ TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
|
|||||||
}
|
}
|
||||||
type = Type::typeinfoinvariant->type;
|
type = Type::typeinfoinvariant->type;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************************** TypeInfoSharedDeclaration **********************/
|
/***************************** TypeInfoSharedDeclaration **********************/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo)
|
TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo)
|
||||||
: TypeInfoDeclaration(tinfo, 0)
|
: TypeInfoDeclaration(tinfo, 0)
|
||||||
{
|
{
|
||||||
@@ -2478,11 +2288,9 @@ TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo)
|
|||||||
}
|
}
|
||||||
type = Type::typeinfoshared->type;
|
type = Type::typeinfoshared->type;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************************** TypeInfoWildDeclaration **********************/
|
/***************************** TypeInfoWildDeclaration **********************/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
TypeInfoWildDeclaration::TypeInfoWildDeclaration(Type *tinfo)
|
TypeInfoWildDeclaration::TypeInfoWildDeclaration(Type *tinfo)
|
||||||
: TypeInfoDeclaration(tinfo, 0)
|
: TypeInfoDeclaration(tinfo, 0)
|
||||||
{
|
{
|
||||||
@@ -2492,7 +2300,6 @@ TypeInfoWildDeclaration::TypeInfoWildDeclaration(Type *tinfo)
|
|||||||
}
|
}
|
||||||
type = Type::typeinfowild->type;
|
type = Type::typeinfowild->type;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************************** TypeInfoStructDeclaration **********************/
|
/***************************** TypeInfoStructDeclaration **********************/
|
||||||
|
|
||||||
@@ -2665,4 +2472,4 @@ Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
|
|||||||
assert(0); // should never be produced by syntax
|
assert(0); // should never be produced by syntax
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-36
@@ -91,16 +91,16 @@ enum PURE;
|
|||||||
#define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild)
|
#define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild)
|
||||||
#define STC_FUNCATTR (STCref | STCnothrow | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem)
|
#define STC_FUNCATTR (STCref | STCnothrow | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem)
|
||||||
|
|
||||||
#define STCproperty 0x100000000LL
|
#define STCproperty 0x100000000LL
|
||||||
#define STCsafe 0x200000000LL
|
#define STCsafe 0x200000000LL
|
||||||
#define STCtrusted 0x400000000LL
|
#define STCtrusted 0x400000000LL
|
||||||
#define STCsystem 0x800000000LL
|
#define STCsystem 0x800000000LL
|
||||||
#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static
|
#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static
|
||||||
#define STCdisable 0x2000000000LL // for functions that are not callable
|
#define STCdisable 0x2000000000LL // for functions that are not callable
|
||||||
#define STCresult 0x4000000000LL // for result variables passed to out contracts
|
#define STCresult 0x4000000000LL // for result variables passed to out contracts
|
||||||
#define STCnodefaultctor 0x8000000000LL // must be set inside constructor
|
#define STCnodefaultctor 0x8000000000LL // must be set inside constructor
|
||||||
#define STCtemp 0x10000000000LL // temporary variable introduced by inlining
|
#define STCtemp 0x10000000000LL // temporary variable
|
||||||
// and used only in backend process, so it's rvalue
|
#define STCrvalue 0x20000000000LL // force rvalue for variables
|
||||||
|
|
||||||
const StorageClass STCStorageClass = (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal |
|
const StorageClass STCStorageClass = (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal |
|
||||||
STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias |
|
STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias |
|
||||||
@@ -288,18 +288,15 @@ public:
|
|||||||
Initializer *init;
|
Initializer *init;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
bool noscope; // no auto semantics
|
bool noscope; // no auto semantics
|
||||||
#if DMDV2
|
|
||||||
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
|
FuncDeclarations nestedrefs; // referenced by these lexically nested functions
|
||||||
bool isargptr; // if parameter that _argptr points to
|
bool isargptr; // if parameter that _argptr points to
|
||||||
#else
|
|
||||||
int nestedref; // referenced by a lexically nested function
|
|
||||||
#endif
|
|
||||||
structalign_t alignment;
|
structalign_t alignment;
|
||||||
bool ctorinit; // it has been initialized in a ctor
|
bool ctorinit; // it has been initialized in a ctor
|
||||||
short onstack; // 1: it has been allocated on the stack
|
short onstack; // 1: it has been allocated on the stack
|
||||||
// 2: on stack, run destructor anyway
|
// 2: on stack, run destructor anyway
|
||||||
int canassign; // it can be assigned to
|
int canassign; // it can be assigned to
|
||||||
Dsymbol *aliassym; // if redone as alias to another symbol
|
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)
|
// 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
|
// The index of this variable on the CTFE stack, -1 if not allocated
|
||||||
@@ -311,12 +308,10 @@ public:
|
|||||||
void setValueWithoutChecking(Expression *newval);
|
void setValueWithoutChecking(Expression *newval);
|
||||||
void setValue(Expression *newval);
|
void setValue(Expression *newval);
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see
|
VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see
|
||||||
// if the destructor should be run. Used to prevent
|
// if the destructor should be run. Used to prevent
|
||||||
// dtor calls on postblitted vars
|
// dtor calls on postblitted vars
|
||||||
Expression *edtor; // if !=NULL, does the destruction of the variable
|
Expression *edtor; // if !=NULL, does the destruction of the variable
|
||||||
#endif
|
|
||||||
|
|
||||||
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
|
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
|
||||||
Dsymbol *syntaxCopy(Dsymbol *);
|
Dsymbol *syntaxCopy(Dsymbol *);
|
||||||
@@ -336,10 +331,8 @@ public:
|
|||||||
bool isThreadlocal();
|
bool isThreadlocal();
|
||||||
bool isCTFE();
|
bool isCTFE();
|
||||||
bool hasPointers();
|
bool hasPointers();
|
||||||
#if DMDV2
|
|
||||||
bool canTakeAddressOf();
|
bool canTakeAddressOf();
|
||||||
bool needsAutoDtor();
|
bool needsAutoDtor();
|
||||||
#endif
|
|
||||||
Expression *callScopeDtor(Scope *sc);
|
Expression *callScopeDtor(Scope *sc);
|
||||||
ExpInitializer *getExpInitializer();
|
ExpInitializer *getExpInitializer();
|
||||||
Expression *getConstInitializer(bool needFullType = true);
|
Expression *getConstInitializer(bool needFullType = true);
|
||||||
@@ -616,7 +609,6 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class TypeInfoConstDeclaration : public TypeInfoDeclaration
|
class TypeInfoConstDeclaration : public TypeInfoDeclaration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -686,7 +678,6 @@ public:
|
|||||||
void llvmDefine();
|
void llvmDefine();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
|
||||||
@@ -706,7 +697,6 @@ enum ILS
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
#if DMDV2
|
|
||||||
|
|
||||||
enum BUILTIN
|
enum BUILTIN
|
||||||
{
|
{
|
||||||
@@ -733,9 +723,6 @@ enum BUILTIN
|
|||||||
|
|
||||||
Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments);
|
Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments);
|
||||||
|
|
||||||
#else
|
|
||||||
enum BUILTIN { };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class FuncDeclaration : public Declaration
|
class FuncDeclaration : public Declaration
|
||||||
{
|
{
|
||||||
@@ -812,8 +799,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ReturnStatements *returns;
|
ReturnStatements *returns;
|
||||||
|
GotoStatements *gotos; // Gotos with forward references
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
BUILTIN builtin; // set if this is a known, builtin
|
BUILTIN builtin; // set if this is a known, builtin
|
||||||
// function we can evaluate at compile
|
// function we can evaluate at compile
|
||||||
// time
|
// time
|
||||||
@@ -834,9 +821,6 @@ public:
|
|||||||
#define FUNCFLAGpurityInprocess 1 // working on determining purity
|
#define FUNCFLAGpurityInprocess 1 // working on determining purity
|
||||||
#define FUNCFLAGsafetyInprocess 2 // working on determining safety
|
#define FUNCFLAGsafetyInprocess 2 // working on determining safety
|
||||||
#define FUNCFLAGnothrowInprocess 4 // working on determining nothrow
|
#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);
|
FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type);
|
||||||
Dsymbol *syntaxCopy(Dsymbol *);
|
Dsymbol *syntaxCopy(Dsymbol *);
|
||||||
@@ -897,7 +881,7 @@ public:
|
|||||||
void ctfeCompile();
|
void ctfeCompile();
|
||||||
void inlineScan();
|
void inlineScan();
|
||||||
int canInline(int hasthis, int hdrscan, int statementsToo);
|
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();
|
const char *kind();
|
||||||
void toDocBuffer(OutBuffer *buf, Scope *sc);
|
void toDocBuffer(OutBuffer *buf, Scope *sc);
|
||||||
FuncDeclaration *isUnique();
|
FuncDeclaration *isUnique();
|
||||||
@@ -960,13 +944,11 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
|
FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
|
||||||
Objects *tiargs,
|
Objects *tiargs,
|
||||||
Type *tthis,
|
Type *tthis,
|
||||||
Expressions *arguments,
|
Expressions *arguments,
|
||||||
int flags = 0);
|
int flags = 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
class FuncAliasDeclaration : public FuncDeclaration
|
class FuncAliasDeclaration : public FuncDeclaration
|
||||||
{
|
{
|
||||||
@@ -1001,6 +983,7 @@ public:
|
|||||||
|
|
||||||
FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
|
FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
|
||||||
const char *kind();
|
const char *kind();
|
||||||
|
const char *toPrettyChars();
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
// If this is only used as alias parameter to a template instantiation,
|
// If this is only used as alias parameter to a template instantiation,
|
||||||
@@ -1028,7 +1011,6 @@ public:
|
|||||||
CtorDeclaration *isCtorDeclaration() { return this; }
|
CtorDeclaration *isCtorDeclaration() { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class PostBlitDeclaration : public FuncDeclaration
|
class PostBlitDeclaration : public FuncDeclaration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1045,7 +1027,6 @@ public:
|
|||||||
|
|
||||||
PostBlitDeclaration *isPostBlitDeclaration() { return this; }
|
PostBlitDeclaration *isPostBlitDeclaration() { return this; }
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class DtorDeclaration : public FuncDeclaration
|
class DtorDeclaration : public FuncDeclaration
|
||||||
{
|
{
|
||||||
@@ -1084,7 +1065,6 @@ public:
|
|||||||
StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
|
StaticCtorDeclaration *isStaticCtorDeclaration() { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class SharedStaticCtorDeclaration : public StaticCtorDeclaration
|
class SharedStaticCtorDeclaration : public StaticCtorDeclaration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1094,7 +1074,6 @@ public:
|
|||||||
|
|
||||||
SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; }
|
SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; }
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class StaticDtorDeclaration : public FuncDeclaration
|
class StaticDtorDeclaration : public FuncDeclaration
|
||||||
{
|
{
|
||||||
@@ -1116,7 +1095,6 @@ public:
|
|||||||
StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
|
StaticDtorDeclaration *isStaticDtorDeclaration() { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class SharedStaticDtorDeclaration : public StaticDtorDeclaration
|
class SharedStaticDtorDeclaration : public StaticDtorDeclaration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1126,7 +1104,6 @@ public:
|
|||||||
|
|
||||||
SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; }
|
SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; }
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class InvariantDeclaration : public FuncDeclaration
|
class InvariantDeclaration : public FuncDeclaration
|
||||||
{
|
{
|
||||||
@@ -1155,6 +1132,7 @@ public:
|
|||||||
bool addPreInvariant();
|
bool addPreInvariant();
|
||||||
bool addPostInvariant();
|
bool addPostInvariant();
|
||||||
void emitComment(Scope *sc);
|
void emitComment(Scope *sc);
|
||||||
|
void inlineScan();
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
|
|
||||||
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
|
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
|
||||||
|
|||||||
+77
-91
@@ -47,10 +47,10 @@ struct Escape
|
|||||||
class Section
|
class Section
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
utf8_t *name;
|
const utf8_t *name;
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
|
|
||||||
utf8_t *body;
|
const utf8_t *body;
|
||||||
size_t bodylen;
|
size_t bodylen;
|
||||||
|
|
||||||
int nooutput;
|
int nooutput;
|
||||||
@@ -86,19 +86,19 @@ struct DocComment
|
|||||||
summary(NULL), copyright(NULL), macros(NULL), pmacrotable(NULL), pescapetable(NULL)
|
summary(NULL), copyright(NULL), macros(NULL), pmacrotable(NULL), pescapetable(NULL)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
static DocComment *parse(Scope *sc, Dsymbol *s, utf8_t *comment);
|
static DocComment *parse(Scope *sc, Dsymbol *s, const utf8_t *comment);
|
||||||
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, utf8_t *m, size_t mlen);
|
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, const utf8_t *m, size_t mlen);
|
||||||
static void parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t textlen);
|
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);
|
void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int cmp(const char *stringz, void *s, size_t slen);
|
int cmp(const char *stringz, const void *s, size_t slen);
|
||||||
int icmp(const char *stringz, void *s, size_t slen);
|
int icmp(const char *stringz, const void *s, size_t slen);
|
||||||
int isDitto(utf8_t *comment);
|
int isDitto(const utf8_t *comment);
|
||||||
utf8_t *skipwhitespace(utf8_t *p);
|
const utf8_t *skipwhitespace(const utf8_t *p);
|
||||||
size_t skiptoident(OutBuffer *buf, size_t i);
|
size_t skiptoident(OutBuffer *buf, size_t i);
|
||||||
size_t skippastident(OutBuffer *buf, size_t i);
|
size_t skippastident(OutBuffer *buf, size_t i);
|
||||||
size_t skippastURL(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 highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool anchor = true);
|
||||||
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
|
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
|
||||||
TypeFunction *isTypeFunction(Dsymbol *s);
|
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);
|
||||||
TemplateParameter *isTemplateParameter(Dsymbol *s, utf8_t *p, size_t len);
|
TemplateParameter *isTemplateParameter(Dsymbol *s, const utf8_t *p, size_t len);
|
||||||
|
|
||||||
int isIdStart(utf8_t *p);
|
int isIdStart(const utf8_t *p);
|
||||||
int isIdTail(utf8_t *p);
|
int isIdTail(const utf8_t *p);
|
||||||
int isIndentWS(utf8_t *p);
|
int isIndentWS(const utf8_t *p);
|
||||||
int utfStride(utf8_t *p);
|
int utfStride(const utf8_t *p);
|
||||||
|
|
||||||
static const char ddoc_default[] = "\
|
static const char ddoc_default[] = "\
|
||||||
DDOC = <html><head>\n\
|
DDOC = <html><head>\n\
|
||||||
@@ -249,7 +249,7 @@ void Module::gendocfile()
|
|||||||
mbuf.write(file.buffer, file.len);
|
mbuf.write(file.buffer, file.len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DocComment::parseMacros(&escapetable, ¯otable, mbuf.data, mbuf.offset);
|
DocComment::parseMacros(&escapetable, ¯otable, (utf8_t *)mbuf.data, mbuf.offset);
|
||||||
|
|
||||||
Scope *sc = Scope::createGlobal(this); // create root scope
|
Scope *sc = Scope::createGlobal(this); // create root scope
|
||||||
sc->docbuf = &buf;
|
sc->docbuf = &buf;
|
||||||
@@ -305,7 +305,7 @@ void Module::gendocfile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//printf("BODY= '%.*s'\n", buf.offset, buf.data);
|
//printf("BODY= '%.*s'\n", buf.offset, buf.data);
|
||||||
Macro::define(¯otable, (utf8_t *)"BODY", 4, buf.data, buf.offset);
|
Macro::define(¯otable, (utf8_t *)"BODY", 4, (utf8_t *)buf.data, buf.offset);
|
||||||
|
|
||||||
OutBuffer buf2;
|
OutBuffer buf2;
|
||||||
buf2.writestring("$(DDOC)\n");
|
buf2.writestring("$(DDOC)\n");
|
||||||
@@ -319,7 +319,7 @@ void Module::gendocfile()
|
|||||||
{
|
{
|
||||||
buf.setsize(0);
|
buf.setsize(0);
|
||||||
buf.reserve(buf2.offset);
|
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++)
|
for (size_t j = 0; j < buf2.offset; j++)
|
||||||
{
|
{
|
||||||
utf8_t c = p[j];
|
utf8_t c = p[j];
|
||||||
@@ -552,7 +552,7 @@ void emitUnittestComment(Scope *sc, Dsymbol *s, size_t ofs)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Strip whitespaces to avoid showing empty summary
|
// 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;
|
while (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r') ++c;
|
||||||
|
|
||||||
OutBuffer codebuf;
|
OutBuffer codebuf;
|
||||||
@@ -665,9 +665,7 @@ void emitProtection(OutBuffer *buf, PROT prot)
|
|||||||
void Dsymbol::emitComment(Scope *sc) { }
|
void Dsymbol::emitComment(Scope *sc) { }
|
||||||
void InvariantDeclaration::emitComment(Scope *sc) { }
|
void InvariantDeclaration::emitComment(Scope *sc) { }
|
||||||
void UnitTestDeclaration::emitComment(Scope *sc) { }
|
void UnitTestDeclaration::emitComment(Scope *sc) { }
|
||||||
#if DMDV2
|
|
||||||
void PostBlitDeclaration::emitComment(Scope *sc) { }
|
void PostBlitDeclaration::emitComment(Scope *sc) { }
|
||||||
#endif
|
|
||||||
void DtorDeclaration::emitComment(Scope *sc) { }
|
void DtorDeclaration::emitComment(Scope *sc) { }
|
||||||
void StaticCtorDeclaration::emitComment(Scope *sc) { }
|
void StaticCtorDeclaration::emitComment(Scope *sc) { }
|
||||||
void StaticDtorDeclaration::emitComment(Scope *sc) { }
|
void StaticDtorDeclaration::emitComment(Scope *sc) { }
|
||||||
@@ -746,7 +744,7 @@ void TemplateDeclaration::emitComment(Scope *sc)
|
|||||||
if (prot() == PROTprivate)
|
if (prot() == PROTprivate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
utf8_t *com = comment;
|
const utf8_t *com = comment;
|
||||||
int hasmembers = 1;
|
int hasmembers = 1;
|
||||||
|
|
||||||
Dsymbol *ss = this;
|
Dsymbol *ss = this;
|
||||||
@@ -900,10 +898,8 @@ void prefix(OutBuffer *buf, Dsymbol *s)
|
|||||||
{
|
{
|
||||||
if (d->isConst())
|
if (d->isConst())
|
||||||
buf->writestring("const ");
|
buf->writestring("const ");
|
||||||
#if DMDV2
|
|
||||||
if (d->isImmutable())
|
if (d->isImmutable())
|
||||||
buf->writestring("immutable ");
|
buf->writestring("immutable ");
|
||||||
#endif
|
|
||||||
if (d->isSynchronized())
|
if (d->isSynchronized())
|
||||||
buf->writestring("synchronized ");
|
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)
|
void AggregateDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
|
||||||
{
|
{
|
||||||
if (ident)
|
if (ident)
|
||||||
@@ -1210,7 +1195,7 @@ void EnumMember::toDocBuffer(OutBuffer *buf, Scope *sc)
|
|||||||
|
|
||||||
/********************************* DocComment *********************************/
|
/********************************* 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);
|
//printf("parse(%s): '%s'\n", s->toChars(), comment);
|
||||||
if (sc->lastdc && isDitto(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.
|
* then (*pcomment)[0 .. idlen] is the identifier.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DocComment::parseSections(utf8_t *comment)
|
void DocComment::parseSections(const utf8_t *comment)
|
||||||
{ utf8_t *p;
|
{
|
||||||
utf8_t *pstart;
|
const utf8_t *p;
|
||||||
utf8_t *pend;
|
const utf8_t *pstart;
|
||||||
utf8_t *idstart;
|
const utf8_t *pend;
|
||||||
|
const utf8_t *idstart;
|
||||||
size_t idlen;
|
size_t idlen;
|
||||||
|
|
||||||
utf8_t *name = NULL;
|
const utf8_t *name = NULL;
|
||||||
size_t namelen = 0;
|
size_t namelen = 0;
|
||||||
|
|
||||||
//printf("parseSections('%s')\n", comment);
|
//printf("parseSections('%s')\n", comment);
|
||||||
p = comment;
|
p = comment;
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
utf8_t *pstart0 = p;
|
const utf8_t *pstart0 = p;
|
||||||
p = skipwhitespace(p);
|
p = skipwhitespace(p);
|
||||||
pstart = p;
|
pstart = p;
|
||||||
pend = p;
|
pend = p;
|
||||||
@@ -1296,7 +1282,7 @@ void DocComment::parseSections(utf8_t *comment)
|
|||||||
|
|
||||||
if (!inCode && isIdStart(p))
|
if (!inCode && isIdStart(p))
|
||||||
{
|
{
|
||||||
utf8_t *q = p + utfStride(p);
|
const utf8_t *q = p + utfStride(p);
|
||||||
while (isIdTail(q))
|
while (isIdTail(q))
|
||||||
q += utfStride(q);
|
q += utfStride(q);
|
||||||
if (*q == ':') // identifier: ends it
|
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)
|
void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||||
{
|
{
|
||||||
utf8_t *p = body;
|
const utf8_t *p = body;
|
||||||
size_t len = bodylen;
|
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;
|
size_t templen;
|
||||||
|
|
||||||
utf8_t *namestart;
|
const utf8_t *namestart;
|
||||||
size_t namelen = 0; // !=0 if line continuation
|
size_t namelen = 0; // !=0 if line continuation
|
||||||
|
|
||||||
utf8_t *textstart;
|
const utf8_t *textstart;
|
||||||
size_t textlen;
|
size_t textlen;
|
||||||
|
|
||||||
size_t o, paramcount = 0;
|
size_t o, paramcount = 0;
|
||||||
@@ -1606,19 +1592,19 @@ void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
|||||||
* name2 = value2
|
* 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;
|
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;
|
size_t templen;
|
||||||
|
|
||||||
utf8_t *namestart;
|
const utf8_t *namestart;
|
||||||
size_t namelen = 0; // !=0 if line continuation
|
size_t namelen = 0; // !=0 if line continuation
|
||||||
|
|
||||||
utf8_t *textstart;
|
const utf8_t *textstart;
|
||||||
size_t textlen;
|
size_t textlen;
|
||||||
|
|
||||||
while (p < pend)
|
while (p < pend)
|
||||||
@@ -1731,7 +1717,7 @@ Ldone:
|
|||||||
* by whitespace and/or commas.
|
* 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;
|
{ Escape *escapetable = *pescapetable;
|
||||||
|
|
||||||
if (!escapetable)
|
if (!escapetable)
|
||||||
@@ -1740,8 +1726,8 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t
|
|||||||
*pescapetable = escapetable;
|
*pescapetable = escapetable;
|
||||||
}
|
}
|
||||||
//printf("parseEscapes('%.*s') pescapetable = %p\n", textlen, textstart, pescapetable);
|
//printf("parseEscapes('%.*s') pescapetable = %p\n", textlen, textstart, pescapetable);
|
||||||
utf8_t *p = textstart;
|
const utf8_t *p = textstart;
|
||||||
utf8_t *pend = p + textlen;
|
const utf8_t *pend = p + textlen;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -1757,7 +1743,7 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t
|
|||||||
return;
|
return;
|
||||||
utf8_t c = p[1];
|
utf8_t c = p[1];
|
||||||
p += 3;
|
p += 3;
|
||||||
utf8_t *start = p;
|
const utf8_t *start = p;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (p >= pend)
|
if (p >= pend)
|
||||||
@@ -1781,7 +1767,7 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t
|
|||||||
* Return < 0, ==0, > 0
|
* 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);
|
size_t len1 = strlen(stringz);
|
||||||
|
|
||||||
@@ -1790,7 +1776,7 @@ int cmp(const char *stringz, void *s, size_t slen)
|
|||||||
return memcmp(stringz, s, 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);
|
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".
|
* Return !=0 if comment consists entirely of "ditto".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int isDitto(utf8_t *comment)
|
int isDitto(const utf8_t *comment)
|
||||||
{
|
{
|
||||||
if (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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1819,7 +1805,7 @@ int isDitto(utf8_t *comment)
|
|||||||
* Skip white space.
|
* Skip white space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
utf8_t *skipwhitespace(utf8_t *p)
|
const utf8_t *skipwhitespace(const utf8_t *p)
|
||||||
{
|
{
|
||||||
for (; 1; p++)
|
for (; 1; p++)
|
||||||
{ switch (*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 skippastURL(OutBuffer *buf, size_t i)
|
||||||
{ size_t length = buf->offset - i;
|
{ size_t length = buf->offset - i;
|
||||||
utf8_t *p = &buf->data[i];
|
utf8_t *p = (utf8_t *)&buf->data[i];
|
||||||
size_t j;
|
size_t j;
|
||||||
unsigned sawdot = 0;
|
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);
|
TypeFunction *tf = isTypeFunction(s);
|
||||||
if (tf && tf->parameters)
|
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();
|
TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||||
if (td && td->origParameters)
|
if (td && td->origParameters)
|
||||||
@@ -2062,7 +2048,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
|||||||
if (!sc->module->isDocFile &&
|
if (!sc->module->isDocFile &&
|
||||||
!inCode && i == iLineStart && i + 1 < buf->offset) // if "\n\n"
|
!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));
|
i = buf->insert(i, blankline, strlen(blankline));
|
||||||
}
|
}
|
||||||
@@ -2074,7 +2060,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
|||||||
leadingBlank = 0;
|
leadingBlank = 0;
|
||||||
if (inCode)
|
if (inCode)
|
||||||
break;
|
break;
|
||||||
p = &buf->data[i];
|
p = (utf8_t *)&buf->data[i];
|
||||||
se = sc->module->escapetable->escapeChar('<');
|
se = sc->module->escapetable->escapeChar('<');
|
||||||
|
|
||||||
if (se && strcmp(se, "<") == 0)
|
if (se && strcmp(se, "<") == 0)
|
||||||
@@ -2148,7 +2134,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
|||||||
leadingBlank = 0;
|
leadingBlank = 0;
|
||||||
if (inCode)
|
if (inCode)
|
||||||
break;
|
break;
|
||||||
p = &buf->data[i];
|
p = (utf8_t *)&buf->data[i];
|
||||||
if (p[1] == '#' || isalpha(p[1]))
|
if (p[1] == '#' || isalpha(p[1]))
|
||||||
break; // already a character entity
|
break; // already a character entity
|
||||||
// Replace '&' with '&' character entity
|
// Replace '&' with '&' character entity
|
||||||
@@ -2220,8 +2206,8 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
|||||||
|
|
||||||
// Remove leading indentations from all lines
|
// Remove leading indentations from all lines
|
||||||
bool lineStart = true;
|
bool lineStart = true;
|
||||||
utf8_t *endp = codebuf.data + codebuf.offset;
|
utf8_t *endp = (utf8_t *)codebuf.data + codebuf.offset;
|
||||||
for (utf8_t *p = codebuf.data; p < endp; )
|
for (p = (utf8_t *)codebuf.data; p < endp; )
|
||||||
{
|
{
|
||||||
if (lineStart)
|
if (lineStart)
|
||||||
{
|
{
|
||||||
@@ -2229,11 +2215,11 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
|||||||
utf8_t *q = p;
|
utf8_t *q = p;
|
||||||
while (j-- > 0 && q < endp && isIndentWS(q))
|
while (j-- > 0 && q < endp && isIndentWS(q))
|
||||||
++q;
|
++q;
|
||||||
codebuf.remove(p - codebuf.data, q - p);
|
codebuf.remove(p - (utf8_t *)codebuf.data, q - p);
|
||||||
assert(codebuf.data <= p);
|
assert((utf8_t *)codebuf.data <= p);
|
||||||
assert(p < codebuf.data + codebuf.offset);
|
assert(p < (utf8_t *)codebuf.data + codebuf.offset);
|
||||||
lineStart = false;
|
lineStart = false;
|
||||||
endp = codebuf.data + codebuf.offset; // update
|
endp = (utf8_t *)codebuf.data + codebuf.offset; // update
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*p == '\n')
|
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'
|
i -= 2; // in next loop, c should be '\n'
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ static char pre[] = "$(D_CODE \n";
|
{ static const char pre[] = "$(D_CODE \n";
|
||||||
|
|
||||||
inCode = 1;
|
inCode = 1;
|
||||||
codeIndent = istart - iLineStart; // save indent count
|
codeIndent = istart - iLineStart; // save indent count
|
||||||
@@ -2263,7 +2249,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
|||||||
default:
|
default:
|
||||||
leadingBlank = 0;
|
leadingBlank = 0;
|
||||||
if (!sc->module->isDocFile &&
|
if (!sc->module->isDocFile &&
|
||||||
!inCode && isIdStart(&buf->data[i]))
|
!inCode && isIdStart((utf8_t *)&buf->data[i]))
|
||||||
{
|
{
|
||||||
size_t j = skippastident(buf, i);
|
size_t j = skippastident(buf, i);
|
||||||
if (j > 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;
|
i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1;
|
||||||
break;
|
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;
|
i = buf->bracket(i, "$(DDOC_KEYWORD ", j, ")") - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
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);
|
//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
|
||||||
i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
|
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 = buf->insert(i, se, len);
|
||||||
i--; // point to ';'
|
i--; // point to ';'
|
||||||
}
|
}
|
||||||
else if (isIdStart(&buf->data[i]))
|
else if (isIdStart((utf8_t *)&buf->data[i]))
|
||||||
{
|
{
|
||||||
size_t j = skippastident(buf, i);
|
size_t j = skippastident(buf, i);
|
||||||
if (j > i)
|
if (j > i)
|
||||||
@@ -2354,7 +2340,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
|
|||||||
}
|
}
|
||||||
else if (f)
|
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);
|
//printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j);
|
||||||
i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1;
|
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++)
|
for (; p < pend; p++)
|
||||||
{ const char *s = sc->module->escapetable->escapeChar(*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();
|
const char *sid = s->ident->toChars();
|
||||||
FuncDeclaration *f = s->isFuncDeclaration();
|
FuncDeclaration *f = s->isFuncDeclaration();
|
||||||
unsigned errorsave = global.errors;
|
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;
|
Token tok;
|
||||||
OutBuffer res;
|
OutBuffer res;
|
||||||
utf8_t *lastp = buf->data;
|
const utf8_t *lastp = (utf8_t *)buf->data;
|
||||||
const char *highlight;
|
const char *highlight;
|
||||||
|
|
||||||
if (s->isModule() && ((Module *)s)->isDocFile)
|
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.
|
* Determine if p points to the start of an identifier.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int isIdStart(utf8_t *p)
|
int isIdStart(const utf8_t *p)
|
||||||
{
|
{
|
||||||
unsigned c = *p;
|
unsigned c = *p;
|
||||||
if (isalpha(c) || c == '_')
|
if (isalpha(c) || c == '_')
|
||||||
@@ -2515,7 +2501,7 @@ int isIdStart(utf8_t *p)
|
|||||||
* Determine if p points to the rest of an identifier.
|
* Determine if p points to the rest of an identifier.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int isIdTail(utf8_t *p)
|
int isIdTail(const utf8_t *p)
|
||||||
{
|
{
|
||||||
unsigned c = *p;
|
unsigned c = *p;
|
||||||
if (isalnum(c) || c == '_')
|
if (isalnum(c) || c == '_')
|
||||||
@@ -2534,7 +2520,7 @@ int isIdTail(utf8_t *p)
|
|||||||
* Determine if p points to the indentation space.
|
* Determine if p points to the indentation space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int isIndentWS(utf8_t *p)
|
int isIndentWS(const utf8_t *p)
|
||||||
{
|
{
|
||||||
return (*p == ' ') || (*p == '\t');
|
return (*p == ' ') || (*p == '\t');
|
||||||
}
|
}
|
||||||
@@ -2543,7 +2529,7 @@ int isIndentWS(utf8_t *p)
|
|||||||
* Return number of bytes in UTF character.
|
* Return number of bytes in UTF character.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int utfStride(utf8_t *p)
|
int utfStride(const utf8_t *p)
|
||||||
{
|
{
|
||||||
unsigned c = *p;
|
unsigned c = *p;
|
||||||
if (c < 0x80)
|
if (c < 0x80)
|
||||||
|
|||||||
+30
-33
@@ -199,7 +199,7 @@ bool Dsymbol::hasPointers()
|
|||||||
bool Dsymbol::hasStaticCtorOrDtor()
|
bool Dsymbol::hasStaticCtorOrDtor()
|
||||||
{
|
{
|
||||||
//printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
|
//printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars());
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
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");
|
//printf("\ttemplate instance id\n");
|
||||||
Dsymbol *st = (Dsymbol *)id;
|
Dsymbol *st = (Dsymbol *)id;
|
||||||
TemplateInstance *ti = st->isTemplateInstance();
|
TemplateInstance *ti = st->isTemplateInstance();
|
||||||
Identifier *id = ti->name;
|
sm = s->search(loc, ti->name, 0);
|
||||||
sm = s->search(loc, id, 0);
|
|
||||||
if (!sm)
|
if (!sm)
|
||||||
{
|
{
|
||||||
sm = s->search_correct(id);
|
sm = s->search_correct(ti->name);
|
||||||
if (sm)
|
if (sm)
|
||||||
error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?",
|
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
|
else
|
||||||
error("template identifier '%s' is not a member of '%s %s'",
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
sm = sm->toAlias();
|
sm = sm->toAlias();
|
||||||
TemplateDeclaration *td = sm->isTemplateDeclaration();
|
TemplateDeclaration *td = sm->isTemplateDeclaration();
|
||||||
if (!td)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
ti->tempdecl = td;
|
ti->tempdecl = td;
|
||||||
@@ -568,7 +567,6 @@ bool Dsymbol::isDeprecated()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
bool Dsymbol::isOverloadable()
|
bool Dsymbol::isOverloadable()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -578,7 +576,6 @@ bool Dsymbol::hasOverloads()
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
|
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
|
||||||
{
|
{
|
||||||
@@ -806,24 +803,21 @@ Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a)
|
|||||||
* Ignore NULL comments.
|
* Ignore NULL comments.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Dsymbol::addComment(utf8_t *comment)
|
void Dsymbol::addComment(const utf8_t *comment)
|
||||||
{
|
{
|
||||||
//if (comment)
|
//if (comment)
|
||||||
//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
|
//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
|
||||||
|
|
||||||
if (!this->comment)
|
if (!this->comment)
|
||||||
this->comment = comment;
|
this->comment = comment;
|
||||||
#if 1
|
|
||||||
else if (comment && strcmp((char *)comment, (char *)this->comment) != 0)
|
else if (comment && strcmp((char *)comment, (char *)this->comment) != 0)
|
||||||
{ // Concatenate the two
|
{ // Concatenate the two
|
||||||
this->comment = Lexer::combineComments(this->comment, comment);
|
this->comment = Lexer::combineComments(this->comment, comment);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************* OverloadSet ****************************/
|
/********************************* OverloadSet ****************************/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
OverloadSet::OverloadSet(Identifier *ident)
|
OverloadSet::OverloadSet(Identifier *ident)
|
||||||
: Dsymbol(ident)
|
: Dsymbol(ident)
|
||||||
{
|
{
|
||||||
@@ -838,7 +832,6 @@ const char *OverloadSet::kind()
|
|||||||
{
|
{
|
||||||
return "overloadset";
|
return "overloadset";
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/********************************* ScopeDsymbol ****************************/
|
/********************************* ScopeDsymbol ****************************/
|
||||||
@@ -1028,7 +1021,7 @@ void ScopeDsymbol::importScope(Dsymbol *s, PROT protection)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
imports->push(s);
|
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;
|
prots[imports->dim - 1] = protection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1115,17 +1108,16 @@ bool ScopeDsymbol::hasStaticCtorOrDtor()
|
|||||||
{ Dsymbol *member = (*members)[i];
|
{ Dsymbol *member = (*members)[i];
|
||||||
|
|
||||||
if (member->hasStaticCtorOrDtor())
|
if (member->hasStaticCtorOrDtor())
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Determine number of Dsymbols, folding in AttribDeclaration members.
|
* Determine number of Dsymbols, folding in AttribDeclaration members.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
static int dimDg(void *ctx, size_t n, Dsymbol *)
|
static int dimDg(void *ctx, size_t n, Dsymbol *)
|
||||||
{
|
{
|
||||||
++*(size_t *)ctx;
|
++*(size_t *)ctx;
|
||||||
@@ -1138,7 +1130,6 @@ size_t ScopeDsymbol::dim(Dsymbols *members)
|
|||||||
foreach(NULL, members, &dimDg, &n);
|
foreach(NULL, members, &dimDg, &n);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Get nth Dsymbol, folding in AttribDeclaration members.
|
* Get nth Dsymbol, folding in AttribDeclaration members.
|
||||||
@@ -1148,7 +1139,6 @@ size_t ScopeDsymbol::dim(Dsymbols *members)
|
|||||||
* of Dsymbols
|
* of Dsymbols
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
struct GetNthSymbolCtx
|
struct GetNthSymbolCtx
|
||||||
{
|
{
|
||||||
size_t nth;
|
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);
|
int res = foreach(NULL, members, &getNthSymbolDg, &ctx);
|
||||||
return res ? ctx.sym : NULL;
|
return res ? ctx.sym : NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Expands attribute declarations in members in depth first
|
* 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.
|
* calculating dim and calling N times getNth.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *ctx, size_t *pn)
|
int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *ctx, size_t *pn)
|
||||||
{
|
{
|
||||||
assert(dg);
|
assert(dg);
|
||||||
@@ -1213,7 +1201,6 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg
|
|||||||
*pn = n; // update index
|
*pn = n; // update index
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*******************************************
|
/*******************************************
|
||||||
* Look for member of the form:
|
* Look for member of the form:
|
||||||
@@ -1221,7 +1208,6 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg
|
|||||||
* Returns NULL if not found
|
* Returns NULL if not found
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
FuncDeclaration *ScopeDsymbol::findGetMembers()
|
FuncDeclaration *ScopeDsymbol::findGetMembers()
|
||||||
{
|
{
|
||||||
Dsymbol *s = search_function(this, Id::getmembers);
|
Dsymbol *s = search_function(this, Id::getmembers);
|
||||||
@@ -1249,7 +1235,6 @@ FuncDeclaration *ScopeDsymbol::findGetMembers()
|
|||||||
|
|
||||||
return fdx;
|
return fdx;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/****************************** WithScopeSymbol ******************************/
|
/****************************** WithScopeSymbol ******************************/
|
||||||
@@ -1267,11 +1252,22 @@ Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
|
|||||||
Expression *eold = NULL;
|
Expression *eold = NULL;
|
||||||
for (Expression *e = withstate->exp; e != eold; e = resolveAliasThis(scope, e))
|
for (Expression *e = withstate->exp; e != eold; e = resolveAliasThis(scope, e))
|
||||||
{
|
{
|
||||||
Type *t = e->type->toBasetype();
|
if (e->op == TOKimport)
|
||||||
if (t->ty == Taarray)
|
{
|
||||||
s = ((TypeAArray *)t)->getImpl();
|
s = ((ScopeExp *)e)->sds;
|
||||||
|
}
|
||||||
|
else if (e->op == TOKtype)
|
||||||
|
{
|
||||||
|
s = e->type->toDsymbol(NULL);
|
||||||
|
}
|
||||||
else
|
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)
|
if (s)
|
||||||
{
|
{
|
||||||
s = s->search(loc, ident, 0);
|
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);
|
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
|
||||||
Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t);
|
Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t);
|
||||||
v->init = new ExpInitializer(Loc(), e);
|
v->init = new ExpInitializer(Loc(), e);
|
||||||
v->storage_class |= STCstatic | STCconst;
|
v->storage_class |= STCtemp | STCstatic | STCconst;
|
||||||
v->semantic(sc);
|
v->semantic(sc);
|
||||||
return v;
|
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);
|
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
|
||||||
Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t);
|
Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t);
|
||||||
v->init = new ExpInitializer(Loc(), e);
|
v->init = new ExpInitializer(Loc(), e);
|
||||||
v->storage_class |= STCstatic | STCconst;
|
v->storage_class |= STCtemp | STCstatic | STCconst;
|
||||||
v->semantic(sc);
|
v->semantic(sc);
|
||||||
return v;
|
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);
|
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 = 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 &&
|
else if (ce->type && (t = ce->type->toBasetype()) != NULL &&
|
||||||
(t->ty == Tstruct || t->ty == Tclass))
|
(t->ty == Tstruct || t->ty == Tclass))
|
||||||
@@ -1473,6 +1469,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
|
|||||||
if (t && t->ty == Tfunction)
|
if (t && t->ty == Tfunction)
|
||||||
e = new CallExp(e->loc, e);
|
e = new CallExp(e->loc, e);
|
||||||
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e));
|
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e));
|
||||||
|
v->storage_class |= STCtemp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* For arrays, $ will either be a compile-time constant
|
{ /* 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());
|
VoidInitializer *e = new VoidInitializer(Loc());
|
||||||
e->type = Type::tsize_t;
|
e->type = Type::tsize_t;
|
||||||
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e);
|
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;
|
*pvar = v;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -146,7 +146,7 @@ public:
|
|||||||
Symbol *csym; // symbol for code generator
|
Symbol *csym; // symbol for code generator
|
||||||
Symbol *isym; // import version of csym
|
Symbol *isym; // import version of csym
|
||||||
#endif
|
#endif
|
||||||
utf8_t *comment; // documentation comment for this Dsymbol
|
const utf8_t *comment; // documentation comment for this Dsymbol
|
||||||
Loc loc; // where defined
|
Loc loc; // where defined
|
||||||
Scope *scope; // !=NULL means context to use for semantic()
|
Scope *scope; // !=NULL means context to use for semantic()
|
||||||
bool errors; // this symbol failed to pass semantic()
|
bool errors; // this symbol failed to pass semantic()
|
||||||
@@ -211,10 +211,8 @@ public:
|
|||||||
virtual bool isExport(); // is Dsymbol exported?
|
virtual bool isExport(); // is Dsymbol exported?
|
||||||
virtual bool isImportedSymbol(); // is Dsymbol imported?
|
virtual bool isImportedSymbol(); // is Dsymbol imported?
|
||||||
virtual bool isDeprecated(); // is Dsymbol deprecated?
|
virtual bool isDeprecated(); // is Dsymbol deprecated?
|
||||||
#if DMDV2
|
|
||||||
virtual bool isOverloadable();
|
virtual bool isOverloadable();
|
||||||
virtual bool hasOverloads();
|
virtual bool hasOverloads();
|
||||||
#endif
|
|
||||||
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
||||||
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
||||||
virtual Type *getType(); // is this a type?
|
virtual Type *getType(); // is this a type?
|
||||||
@@ -230,7 +228,7 @@ public:
|
|||||||
virtual void addLocalClass(ClassDeclarations *) { }
|
virtual void addLocalClass(ClassDeclarations *) { }
|
||||||
virtual void checkCtorConstInit() { }
|
virtual void checkCtorConstInit() { }
|
||||||
|
|
||||||
virtual void addComment(utf8_t *comment);
|
virtual void addComment(const utf8_t *comment);
|
||||||
virtual void emitComment(Scope *sc);
|
virtual void emitComment(Scope *sc);
|
||||||
void emitDitto(Scope *sc);
|
void emitDitto(Scope *sc);
|
||||||
|
|
||||||
@@ -310,7 +308,7 @@ public:
|
|||||||
DsymbolTable *symtab; // members[] sorted into table
|
DsymbolTable *symtab; // members[] sorted into table
|
||||||
|
|
||||||
Dsymbols *imports; // imported Dsymbol's
|
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();
|
||||||
ScopeDsymbol(Identifier *id);
|
ScopeDsymbol(Identifier *id);
|
||||||
@@ -370,7 +368,6 @@ public:
|
|||||||
|
|
||||||
// Overload Sets
|
// Overload Sets
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class OverloadSet : public Dsymbol
|
class OverloadSet : public Dsymbol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -381,7 +378,6 @@ public:
|
|||||||
OverloadSet *isOverloadSet() { return this; }
|
OverloadSet *isOverloadSet() { return this; }
|
||||||
const char *kind();
|
const char *kind();
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
// Table of Dsymbol's
|
// Table of Dsymbol's
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2374,7 +2374,7 @@ static NameId* namesTable[] = {
|
|||||||
namesS, namesT, namesU, namesV, namesW, namesX, namesY, namesZ, NULL
|
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';
|
int tableIndex = tolower(*p) - 'a';
|
||||||
if (tableIndex >= 0 && tableIndex < 26)
|
if (tableIndex >= 0 && tableIndex < 26)
|
||||||
|
|||||||
+4
-3
@@ -381,20 +381,21 @@ Type *EnumDeclaration::getMemtype(Loc loc)
|
|||||||
if (loc.linnum == 0)
|
if (loc.linnum == 0)
|
||||||
loc = this->loc;
|
loc = this->loc;
|
||||||
if (scope)
|
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
|
* just the base type
|
||||||
*/
|
*/
|
||||||
if (memtype)
|
if (memtype)
|
||||||
memtype = memtype->semantic(loc, scope);
|
memtype = memtype->semantic(loc, scope);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!isAnonymous())
|
if (!isAnonymous() && members)
|
||||||
memtype = Type::tint32;
|
memtype = Type::tint32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!memtype)
|
if (!memtype)
|
||||||
{
|
{
|
||||||
if (!isAnonymous())
|
if (!isAnonymous() && members)
|
||||||
memtype = Type::tint32;
|
memtype = Type::tint32;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,9 +57,7 @@ public:
|
|||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
Type *getType();
|
Type *getType();
|
||||||
const char *kind();
|
const char *kind();
|
||||||
#if DMDV2
|
|
||||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||||
#endif
|
|
||||||
bool isDeprecated(); // is Dsymbol deprecated?
|
bool isDeprecated(); // is Dsymbol deprecated?
|
||||||
PROT prot();
|
PROT prot();
|
||||||
Expression *getMaxMinValue(Loc loc, Identifier *id);
|
Expression *getMaxMinValue(Loc loc, Identifier *id);
|
||||||
|
|||||||
+536
-603
File diff suppressed because it is too large
Load Diff
+114
-59
@@ -104,14 +104,14 @@ int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
|
|||||||
TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s);
|
TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s);
|
||||||
Expression *valueNoDtor(Expression *e);
|
Expression *valueNoDtor(Expression *e);
|
||||||
int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
|
int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
|
||||||
#if DMDV2
|
|
||||||
Expression *resolveAliasThis(Scope *sc, Expression *e);
|
Expression *resolveAliasThis(Scope *sc, Expression *e);
|
||||||
Expression *callCpCtor(Scope *sc, Expression *e);
|
Expression *callCpCtor(Scope *sc, Expression *e);
|
||||||
#endif
|
|
||||||
Expression *resolveOpDollar(Scope *sc, ArrayExp *ae);
|
Expression *resolveOpDollar(Scope *sc, ArrayExp *ae);
|
||||||
Expression *resolveOpDollar(Scope *sc, SliceExp *se);
|
Expression *resolveOpDollar(Scope *sc, SliceExp *se);
|
||||||
Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc);
|
Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc);
|
||||||
|
|
||||||
|
AggregateDeclaration *isAggregate(Type *t);
|
||||||
|
|
||||||
/* Run CTFE on the expression, but allow the expression to be a TypeExp
|
/* 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)).
|
* or a tuple containing a TypeExp. (This is required by pragma(msg)).
|
||||||
*/
|
*/
|
||||||
@@ -197,7 +197,6 @@ public:
|
|||||||
Expression *addressOf(Scope *sc);
|
Expression *addressOf(Scope *sc);
|
||||||
Expression *deref();
|
Expression *deref();
|
||||||
Expression *integralPromotions(Scope *sc);
|
Expression *integralPromotions(Scope *sc);
|
||||||
Expression *isTemp();
|
|
||||||
|
|
||||||
Expression *toDelegate(Scope *sc, Type *t);
|
Expression *toDelegate(Scope *sc, Type *t);
|
||||||
|
|
||||||
@@ -216,7 +215,7 @@ public:
|
|||||||
bool hasSideEffect();
|
bool hasSideEffect();
|
||||||
void discardValue();
|
void discardValue();
|
||||||
void useValue();
|
void useValue();
|
||||||
int canThrow(bool mustNotThrow);
|
bool canThrow(bool mustNotThrow);
|
||||||
|
|
||||||
virtual int inlineCost3(InlineCostState *ics);
|
virtual int inlineCost3(InlineCostState *ics);
|
||||||
virtual Expression *doInline(InlineDoState *ids);
|
virtual Expression *doInline(InlineDoState *ids);
|
||||||
@@ -467,7 +466,7 @@ public:
|
|||||||
int isLvalue();
|
int isLvalue();
|
||||||
Expression *toLvalue(Scope *sc, Expression *e);
|
Expression *toLvalue(Scope *sc, Expression *e);
|
||||||
Expression *modifiableLvalue(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 toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
void toMangleBuffer(OutBuffer *buf);
|
void toMangleBuffer(OutBuffer *buf);
|
||||||
elem *toElem(IRState *irs);
|
elem *toElem(IRState *irs);
|
||||||
@@ -626,6 +625,7 @@ public:
|
|||||||
void toMangleBuffer(OutBuffer *buf);
|
void toMangleBuffer(OutBuffer *buf);
|
||||||
Expression *optimize(int result, bool keepLvalue = false);
|
Expression *optimize(int result, bool keepLvalue = false);
|
||||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||||
|
Expression *addDtorHook(Scope *sc);
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
// With the introduction of pointers returned from CTFE, struct literals can
|
// With the introduction of pointers returned from CTFE, struct literals can
|
||||||
// now contain pointers to themselves. While in toElem, contains a pointer
|
// now contain pointers to themselves. While in toElem, contains a pointer
|
||||||
@@ -742,7 +742,6 @@ public:
|
|||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class SymbolExp : public Expression
|
class SymbolExp : public Expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -753,16 +752,15 @@ public:
|
|||||||
|
|
||||||
elem *toElem(IRState *irs);
|
elem *toElem(IRState *irs);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
// Offset from symbol
|
// Offset from symbol
|
||||||
|
|
||||||
class SymOffExp : public SymbolExp
|
class SymOffExp : public SymbolExp
|
||||||
{
|
{
|
||||||
public:
|
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 *semantic(Scope *sc);
|
||||||
Expression *optimize(int result, bool keepLvalue = false);
|
Expression *optimize(int result, bool keepLvalue = false);
|
||||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||||
@@ -814,7 +812,6 @@ public:
|
|||||||
//Expression *inlineScan(InlineScanState *iss);
|
//Expression *inlineScan(InlineScanState *iss);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
// Overload Set
|
// Overload Set
|
||||||
|
|
||||||
class OverExp : public Expression
|
class OverExp : public Expression
|
||||||
@@ -827,7 +824,6 @@ public:
|
|||||||
Expression *toLvalue(Scope *sc, Expression *e);
|
Expression *toLvalue(Scope *sc, Expression *e);
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
// Function/Delegate literal
|
// Function/Delegate literal
|
||||||
|
|
||||||
@@ -892,7 +888,6 @@ public:
|
|||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class TraitsExp : public Expression
|
class TraitsExp : public Expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -902,9 +897,11 @@ public:
|
|||||||
TraitsExp(Loc loc, Identifier *ident, Objects *args);
|
TraitsExp(Loc loc, Identifier *ident, Objects *args);
|
||||||
Expression *syntaxCopy();
|
Expression *syntaxCopy();
|
||||||
Expression *semantic(Scope *sc);
|
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);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class HaltExp : public Expression
|
class HaltExp : public Expression
|
||||||
{
|
{
|
||||||
@@ -1177,11 +1174,13 @@ public:
|
|||||||
int isLvalue();
|
int isLvalue();
|
||||||
Expression *toLvalue(Scope *sc, Expression *e);
|
Expression *toLvalue(Scope *sc, Expression *e);
|
||||||
Expression *addDtorHook(Scope *sc);
|
Expression *addDtorHook(Scope *sc);
|
||||||
|
Expression *implicitCastTo(Scope *sc, Type *t);
|
||||||
MATCH implicitConvTo(Type *t);
|
MATCH implicitConvTo(Type *t);
|
||||||
|
|
||||||
int inlineCost3(InlineCostState *ics);
|
int inlineCost3(InlineCostState *ics);
|
||||||
Expression *doInline(InlineDoState *ids);
|
Expression *doInline(InlineDoState *ids);
|
||||||
Expression *inlineScan(InlineScanState *iss);
|
Expression *inlineScan(InlineScanState *iss);
|
||||||
|
Expression *inlineScan(InlineScanState *iss, Expression *eret);
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
void cacheLvalue(IRState* p);
|
void cacheLvalue(IRState* p);
|
||||||
@@ -1307,10 +1306,10 @@ class CastExp : public UnaExp
|
|||||||
public:
|
public:
|
||||||
// Possible to cast to one type while painting to another type
|
// Possible to cast to one type while painting to another type
|
||||||
Type *to; // type to cast to
|
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, Type *t);
|
||||||
CastExp(Loc loc, Expression *e, unsigned mod);
|
CastExp(Loc loc, Expression *e, unsigned char mod);
|
||||||
Expression *syntaxCopy();
|
Expression *syntaxCopy();
|
||||||
Expression *semantic(Scope *sc);
|
Expression *semantic(Scope *sc);
|
||||||
MATCH implicitConvTo(Type *t);
|
MATCH implicitConvTo(Type *t);
|
||||||
@@ -1517,6 +1516,9 @@ public:
|
|||||||
Identifier *opId(); // For operator overloading
|
Identifier *opId(); // For operator overloading
|
||||||
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
||||||
Expression *buildArrayLoop(Parameters *fparams);
|
Expression *buildArrayLoop(Parameters *fparams);
|
||||||
|
|
||||||
|
Expression *inlineScan(InlineScanState *iss);
|
||||||
|
|
||||||
elem *toElem(IRState *irs);
|
elem *toElem(IRState *irs);
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
@@ -1530,53 +1532,111 @@ public:
|
|||||||
ConstructExp(Loc loc, Expression *e1, Expression *e2);
|
ConstructExp(Loc loc, Expression *e1, Expression *e2);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ASSIGNEXP(op) \
|
class AddAssignExp : public BinAssignExp
|
||||||
class op##AssignExp : public BinAssignExp \
|
{
|
||||||
{ \
|
public:
|
||||||
public: \
|
AddAssignExp(Loc loc, Expression *e1, Expression *e2);
|
||||||
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
|
Identifier *opId(); /* For operator overloading */
|
||||||
S(Expression *semantic(Scope *sc);) \
|
elem *toElem(IRState *irs);
|
||||||
\
|
|
||||||
Identifier *opId(); /* For operator overloading */ \
|
|
||||||
\
|
|
||||||
elem *toElem(IRState *irs); \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define X(a) a
|
class MinAssignExp : public BinAssignExp
|
||||||
#define S(a)
|
{
|
||||||
ASSIGNEXP(Add)
|
public:
|
||||||
ASSIGNEXP(Min)
|
MinAssignExp(Loc loc, Expression *e1, Expression *e2);
|
||||||
ASSIGNEXP(Mul)
|
Identifier *opId(); /* For operator overloading */
|
||||||
ASSIGNEXP(Div)
|
elem *toElem(IRState *irs);
|
||||||
ASSIGNEXP(Mod)
|
};
|
||||||
ASSIGNEXP(And)
|
|
||||||
ASSIGNEXP(Or)
|
|
||||||
ASSIGNEXP(Xor)
|
|
||||||
#undef S
|
|
||||||
|
|
||||||
#if DMDV2
|
class MulAssignExp : public BinAssignExp
|
||||||
#define S(a) a
|
{
|
||||||
ASSIGNEXP(Pow)
|
public:
|
||||||
#undef S
|
MulAssignExp(Loc loc, Expression *e1, Expression *e2);
|
||||||
#endif
|
Identifier *opId(); /* For operator overloading */
|
||||||
|
elem *toElem(IRState *irs);
|
||||||
|
};
|
||||||
|
|
||||||
#undef S
|
class DivAssignExp : public BinAssignExp
|
||||||
#undef X
|
{
|
||||||
|
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)
|
class AndAssignExp : public BinAssignExp
|
||||||
ASSIGNEXP(Shl)
|
{
|
||||||
ASSIGNEXP(Shr)
|
public:
|
||||||
ASSIGNEXP(Ushr)
|
AndAssignExp(Loc loc, Expression *e1, Expression *e2);
|
||||||
#undef S
|
Identifier *opId(); /* For operator overloading */
|
||||||
|
elem *toElem(IRState *irs);
|
||||||
|
};
|
||||||
|
|
||||||
#define S(a) a
|
class OrAssignExp : public BinAssignExp
|
||||||
ASSIGNEXP(Cat)
|
{
|
||||||
#undef S
|
public:
|
||||||
|
OrAssignExp(Loc loc, Expression *e1, Expression *e2);
|
||||||
|
Identifier *opId(); /* For operator overloading */
|
||||||
|
elem *toElem(IRState *irs);
|
||||||
|
};
|
||||||
|
|
||||||
#undef X
|
class XorAssignExp : public BinAssignExp
|
||||||
#undef ASSIGNEXP
|
{
|
||||||
|
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
|
class AddExp : public BinExp
|
||||||
{
|
{
|
||||||
@@ -1678,7 +1738,6 @@ public:
|
|||||||
elem *toElem(IRState *irs);
|
elem *toElem(IRState *irs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class PowExp : public BinExp
|
class PowExp : public BinExp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1692,7 +1751,6 @@ public:
|
|||||||
|
|
||||||
elem *toElem(IRState *irs);
|
elem *toElem(IRState *irs);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class ShlExp : public BinExp
|
class ShlExp : public BinExp
|
||||||
{
|
{
|
||||||
@@ -1914,7 +1972,6 @@ public:
|
|||||||
elem *toElem(IRState *irs);
|
elem *toElem(IRState *irs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
|
|
||||||
class DefaultInitExp : public Expression
|
class DefaultInitExp : public Expression
|
||||||
@@ -1966,8 +2023,6 @@ public:
|
|||||||
Expression *resolveLoc(Loc loc, Scope *sc);
|
Expression *resolveLoc(Loc loc, Scope *sc);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
|
|||||||
+168
-127
@@ -79,9 +79,6 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
|
|||||||
isArrayOp = 0;
|
isArrayOp = 0;
|
||||||
dArrayOp = NULL;
|
dArrayOp = NULL;
|
||||||
semantic3Errors = 0;
|
semantic3Errors = 0;
|
||||||
#if DMDV1
|
|
||||||
nestedFrameRef = 0;
|
|
||||||
#endif
|
|
||||||
fes = NULL;
|
fes = NULL;
|
||||||
introducing = 0;
|
introducing = 0;
|
||||||
tintro = NULL;
|
tintro = NULL;
|
||||||
@@ -96,13 +93,12 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
|
|||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
shidden = NULL;
|
shidden = NULL;
|
||||||
#endif
|
#endif
|
||||||
#if DMDV2
|
|
||||||
builtin = BUILTINunknown;
|
builtin = BUILTINunknown;
|
||||||
tookAddressOf = 0;
|
tookAddressOf = 0;
|
||||||
requiresClosure = false;
|
requiresClosure = false;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
#endif
|
|
||||||
returns = NULL;
|
returns = NULL;
|
||||||
|
gotos = NULL;
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
// LDC
|
// LDC
|
||||||
@@ -165,7 +161,6 @@ static Parameters *outToRef(Parameters* params)
|
|||||||
void FuncDeclaration::semantic(Scope *sc)
|
void FuncDeclaration::semantic(Scope *sc)
|
||||||
{ TypeFunction *f;
|
{ TypeFunction *f;
|
||||||
AggregateDeclaration *ad;
|
AggregateDeclaration *ad;
|
||||||
StructDeclaration *sd;
|
|
||||||
ClassDeclaration *cd;
|
ClassDeclaration *cd;
|
||||||
InterfaceDeclaration *id;
|
InterfaceDeclaration *id;
|
||||||
bool doesoverride;
|
bool doesoverride;
|
||||||
@@ -215,6 +210,8 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
if (StructDeclaration *sd = ad->isStructDeclaration())
|
if (StructDeclaration *sd = ad->isStructDeclaration())
|
||||||
sd->makeNested();
|
sd->makeNested();
|
||||||
}
|
}
|
||||||
|
if (sc->func)
|
||||||
|
storage_class |= sc->func->storage_class & STCdisable;
|
||||||
// Remove prefix storage classes silently.
|
// Remove prefix storage classes silently.
|
||||||
if ((storage_class & STC_TYPECTOR) && !(ad || isNested()))
|
if ((storage_class & STC_TYPECTOR) && !(ad || isNested()))
|
||||||
storage_class &= ~STC_TYPECTOR;
|
storage_class &= ~STC_TYPECTOR;
|
||||||
@@ -223,7 +220,17 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
FuncLiteralDeclaration *fld = isFuncLiteralDeclaration();
|
FuncLiteralDeclaration *fld = isFuncLiteralDeclaration();
|
||||||
if (fld && fld->treq)
|
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
|
else
|
||||||
linkage = sc->linkage;
|
linkage = sc->linkage;
|
||||||
protection = sc->protection;
|
protection = sc->protection;
|
||||||
@@ -360,7 +367,12 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
storage_class &= ~STCref;
|
storage_class &= ~STCref;
|
||||||
if (type->ty != Tfunction)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
f = (TypeFunction *)type;
|
f = (TypeFunction *)type;
|
||||||
@@ -407,7 +419,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sd = parent->isStructDeclaration();
|
StructDeclaration *sd = parent->isStructDeclaration();
|
||||||
if (sd)
|
if (sd)
|
||||||
{
|
{
|
||||||
if (isCtorDeclaration())
|
if (isCtorDeclaration())
|
||||||
@@ -446,9 +458,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
storage_class |= STCabstract;
|
storage_class |= STCabstract;
|
||||||
|
|
||||||
if (isCtorDeclaration() ||
|
if (isCtorDeclaration() ||
|
||||||
#if DMDV2
|
|
||||||
isPostBlitDeclaration() ||
|
isPostBlitDeclaration() ||
|
||||||
#endif
|
|
||||||
isDtorDeclaration() ||
|
isDtorDeclaration() ||
|
||||||
isInvariantDeclaration() ||
|
isInvariantDeclaration() ||
|
||||||
isNewDeclaration() || isDelete())
|
isNewDeclaration() || isDelete())
|
||||||
@@ -496,12 +506,12 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
continue;
|
continue;
|
||||||
for (size_t j = 0; j < cbd->vtbl.dim; j++)
|
for (size_t j = 0; j < cbd->vtbl.dim; j++)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f = cbd->vtbl[j]->isFuncDeclaration();
|
FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration();
|
||||||
if (!f || f->ident != ident)
|
if (!f2 || f2->ident != ident)
|
||||||
continue;
|
continue;
|
||||||
if (cbd->parent && cbd->parent->isTemplateInstance())
|
if (cbd->parent && cbd->parent->isTemplateInstance())
|
||||||
{
|
{
|
||||||
if (!f->functionSemantic())
|
if (!f2->functionSemantic())
|
||||||
goto Ldone;
|
goto Ldone;
|
||||||
}
|
}
|
||||||
may_override = true;
|
may_override = true;
|
||||||
@@ -521,7 +531,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
|
vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
|
||||||
: -1;
|
: -1;
|
||||||
|
|
||||||
doesoverride = FALSE;
|
doesoverride = false;
|
||||||
switch (vi)
|
switch (vi)
|
||||||
{
|
{
|
||||||
case (size_t)-1:
|
case (size_t)-1:
|
||||||
@@ -536,12 +546,12 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
{ Dsymbol *s = cd->baseClass->search(loc, ident, 0);
|
{ Dsymbol *s = cd->baseClass->search(loc, ident, 0);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f = s->isFuncDeclaration();
|
FuncDeclaration *f2 = s->isFuncDeclaration();
|
||||||
if (f)
|
if (f2)
|
||||||
{
|
{
|
||||||
f = f->overloadExactMatch(type);
|
f2 = f2->overloadExactMatch(type);
|
||||||
if (f && f->isFinalFunc() && f->prot() != PROTprivate)
|
if (f2 && f2->isFinalFunc() && f2->prot() != PROTprivate)
|
||||||
error("cannot override final function %s", f->toPrettyChars());
|
error("cannot override final function %s", f2->toPrettyChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,7 +586,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
if (fdc == this)
|
if (fdc == this)
|
||||||
{
|
{
|
||||||
doesoverride = TRUE;
|
doesoverride = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,11 +606,9 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
if (fdv->isFinalFunc())
|
if (fdv->isFinalFunc())
|
||||||
error("cannot override final function %s", fdv->toPrettyChars());
|
error("cannot override final function %s", fdv->toPrettyChars());
|
||||||
|
|
||||||
doesoverride = TRUE;
|
doesoverride = true;
|
||||||
#if DMDV2
|
|
||||||
if (!isOverride())
|
if (!isOverride())
|
||||||
::deprecation(loc, "overriding base class function without using override attribute is deprecated (%s overrides %s)", toPrettyChars(), fdv->toPrettyChars());
|
::deprecation(loc, "overriding base class function without using override attribute is deprecated (%s overrides %s)", toPrettyChars(), fdv->toPrettyChars());
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fdc->toParent() == parent)
|
if (fdc->toParent() == parent)
|
||||||
{
|
{
|
||||||
@@ -675,13 +683,11 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
*/
|
*/
|
||||||
foverrides.push(fdv);
|
foverrides.push(fdv);
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
/* Should we really require 'override' when implementing
|
/* Should we really require 'override' when implementing
|
||||||
* an interface function?
|
* an interface function?
|
||||||
*/
|
*/
|
||||||
//if (!isOverride())
|
//if (!isOverride())
|
||||||
//warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
|
//warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fdv->tintro)
|
if (fdv->tintro)
|
||||||
ti = fdv->tintro;
|
ti = fdv->tintro;
|
||||||
@@ -754,12 +760,12 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
Dsymbol *s = search_function(b->base, ident);
|
Dsymbol *s = search_function(b->base, ident);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f = s->isFuncDeclaration();
|
FuncDeclaration *f2 = s->isFuncDeclaration();
|
||||||
if (f)
|
if (f2)
|
||||||
{
|
{
|
||||||
f = f->overloadExactMatch(type);
|
f2 = f2->overloadExactMatch(type);
|
||||||
if (f && f->isFinalFunc() && f->prot() != PROTprivate)
|
if (f2 && f2->isFinalFunc() && f2->prot() != PROTprivate)
|
||||||
error("cannot override final function %s.%s", b->base->toChars(), f->toPrettyChars());
|
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
|
// If it's a member template
|
||||||
ClassDeclaration *cd = ti->tempdecl->isClassMember();
|
ClassDeclaration *cd2 = ti->tempdecl->isClassMember();
|
||||||
if (cd)
|
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;
|
printedMain = true;
|
||||||
const char *name = FileName::searchPath(global.path, mod->srcfile->toChars(), 1);
|
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())
|
if (fbody && isMain() && sc->module->isRoot())
|
||||||
genCmain(sc);
|
genCmain(sc);
|
||||||
|
|
||||||
return;
|
assert(type->ty != Terror || errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuncDeclaration::semantic2(Scope *sc)
|
void FuncDeclaration::semantic2(Scope *sc)
|
||||||
@@ -1133,8 +1139,6 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
// Declare hidden variable _arguments[] and _argptr
|
// Declare hidden variable _arguments[] and _argptr
|
||||||
if (f->varargs == 1)
|
if (f->varargs == 1)
|
||||||
{
|
{
|
||||||
Type *t;
|
|
||||||
|
|
||||||
#if !IN_GCC && !IN_LLVM
|
#if !IN_GCC && !IN_LLVM
|
||||||
if (global.params.is64bit && !global.params.isWindows)
|
if (global.params.is64bit && !global.params.isWindows)
|
||||||
{ // Declare save area for varargs registers
|
{ // Declare save area for varargs registers
|
||||||
@@ -1148,6 +1152,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
|
v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
|
||||||
|
v_argsave->storage_class |= STCtemp;
|
||||||
v_argsave->semantic(sc2);
|
v_argsave->semantic(sc2);
|
||||||
sc2->insert(v_argsave);
|
sc2->insert(v_argsave);
|
||||||
v_argsave->parent = this;
|
v_argsave->parent = this;
|
||||||
@@ -1158,22 +1163,24 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
if (f->linkage == LINKd)
|
if (f->linkage == LINKd)
|
||||||
{ // Declare _arguments[]
|
{ // Declare _arguments[]
|
||||||
v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
|
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);
|
v_arguments->semantic(sc2);
|
||||||
sc2->insert(v_arguments);
|
sc2->insert(v_arguments);
|
||||||
v_arguments->parent = this;
|
v_arguments->parent = this;
|
||||||
|
|
||||||
//t = Type::typeinfo->type->constOf()->arrayOf();
|
//Type *t = Type::typeinfo->type->constOf()->arrayOf();
|
||||||
t = Type::dtypeinfo->type->arrayOf();
|
Type *t = Type::dtypeinfo->type->arrayOf();
|
||||||
_arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
|
_arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
|
||||||
|
_arguments->storage_class |= STCtemp;
|
||||||
_arguments->semantic(sc2);
|
_arguments->semantic(sc2);
|
||||||
sc2->insert(_arguments);
|
sc2->insert(_arguments);
|
||||||
_arguments->parent = this;
|
_arguments->parent = this;
|
||||||
}
|
}
|
||||||
if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
|
if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
|
||||||
{ // Declare _argptr
|
{ // Declare _argptr
|
||||||
t = Type::tvalist;
|
Type *t = Type::tvalist;
|
||||||
argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
|
argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
|
||||||
|
argptr->storage_class |= STCtemp;
|
||||||
argptr->semantic(sc2);
|
argptr->semantic(sc2);
|
||||||
sc2->insert(argptr);
|
sc2->insert(argptr);
|
||||||
argptr->parent = this;
|
argptr->parent = this;
|
||||||
@@ -1237,20 +1244,23 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
{
|
{
|
||||||
Parameter *arg = Parameter::getNth(f->parameters, i);
|
Parameter *arg = Parameter::getNth(f->parameters, i);
|
||||||
Identifier *id = arg->ident;
|
Identifier *id = arg->ident;
|
||||||
|
StorageClass stc = 0;
|
||||||
if (!id)
|
if (!id)
|
||||||
{
|
{
|
||||||
/* Generate identifier for un-named parameter,
|
/* Generate identifier for un-named parameter,
|
||||||
* because we need it later on.
|
* because we need it later on.
|
||||||
*/
|
*/
|
||||||
arg->ident = id = Identifier::generateId("_param_", i);
|
arg->ident = id = Identifier::generateId("_param_", i);
|
||||||
|
stc |= STCtemp;
|
||||||
}
|
}
|
||||||
Type *vtype = arg->type;
|
Type *vtype = arg->type;
|
||||||
VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
|
VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
|
||||||
//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
|
//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
|
||||||
v->storage_class |= STCparameter;
|
stc |= STCparameter;
|
||||||
if (f->varargs == 2 && i + 1 == nparams)
|
if (f->varargs == 2 && i + 1 == nparams)
|
||||||
v->storage_class |= STCvariadic;
|
stc |= STCvariadic;
|
||||||
v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
|
stc |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
|
||||||
|
v->storage_class = stc;
|
||||||
v->semantic(sc2);
|
v->semantic(sc2);
|
||||||
if (!sc2->insert(v))
|
if (!sc2->insert(v))
|
||||||
error("parameter %s.%s is already defined", toChars(), v->toChars());
|
error("parameter %s.%s is already defined", toChars(), v->toChars());
|
||||||
@@ -1410,17 +1420,17 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
sym->parent = sc2->scopesym;
|
sym->parent = sc2->scopesym;
|
||||||
sc2 = sc2->push(sym);
|
sc2 = sc2->push(sym);
|
||||||
|
|
||||||
AggregateDeclaration *ad = isAggregateMember2();
|
AggregateDeclaration *ad2 = isAggregateMember2();
|
||||||
|
|
||||||
/* If this is a class constructor
|
/* If this is a class constructor
|
||||||
*/
|
*/
|
||||||
if (ad && isCtorDeclaration())
|
if (ad2 && isCtorDeclaration())
|
||||||
{
|
{
|
||||||
sc2->fieldinit = new unsigned[ad->fields.dim];
|
sc2->fieldinit = (unsigned *)mem.malloc(sizeof(unsigned) * ad2->fields.dim);
|
||||||
sc2->fieldinit_dim = ad->fields.dim;
|
sc2->fieldinit_dim = ad2->fields.dim;
|
||||||
for (size_t i = 0; i < ad->fields.dim; i++)
|
for (size_t i = 0; i < ad2->fields.dim; i++)
|
||||||
{
|
{
|
||||||
VarDeclaration *v = ad->fields[i];
|
VarDeclaration *v = ad2->fields[i];
|
||||||
v->ctorinit = 0;
|
v->ctorinit = 0;
|
||||||
sc2->fieldinit[i] = 0;
|
sc2->fieldinit[i] = 0;
|
||||||
}
|
}
|
||||||
@@ -1483,26 +1493,15 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
|
|
||||||
if (fbody->isErrorStatement())
|
if (fbody->isErrorStatement())
|
||||||
;
|
;
|
||||||
else if (isCtorDeclaration() && ad)
|
else if (isCtorDeclaration() && ad2)
|
||||||
{
|
{
|
||||||
#if DMDV2
|
ClassDeclaration *cd = ad2->isClassDeclaration();
|
||||||
// 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();
|
|
||||||
|
|
||||||
// Verify that all the ctorinit fields got initialized
|
// Verify that all the ctorinit fields got initialized
|
||||||
if (!(sc2->callSuper & CSXthis_ctor))
|
if (!(sc2->callSuper & CSXthis_ctor))
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ad->fields.dim; i++)
|
for (size_t i = 0; i < ad2->fields.dim; i++)
|
||||||
{ VarDeclaration *v = ad->fields[i];
|
{ VarDeclaration *v = ad2->fields[i];
|
||||||
|
|
||||||
if (v->ctorinit == 0)
|
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 = NULL;
|
||||||
sc2->fieldinit_dim = 0;
|
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:
|
/* Append:
|
||||||
* return this;
|
* return this;
|
||||||
* to function body
|
* to function body
|
||||||
@@ -1585,7 +1593,6 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if DMDV2
|
|
||||||
// Check for errors related to 'nothrow'.
|
// Check for errors related to 'nothrow'.
|
||||||
int nothrowErrors = global.errors;
|
int nothrowErrors = global.errors;
|
||||||
int blockexit = fbody->blockExit(f->isnothrow);
|
int blockexit = fbody->blockExit(f->isnothrow);
|
||||||
@@ -1598,16 +1605,11 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int offend = blockexit & BEfallthru;
|
int offend = blockexit & BEfallthru;
|
||||||
#endif
|
|
||||||
if (type->nextOf()->ty != Tvoid)
|
if (type->nextOf()->ty != Tvoid)
|
||||||
{
|
{
|
||||||
if (offend)
|
if (offend)
|
||||||
{ Expression *e;
|
{ 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");
|
error("no return exp; or assert(0); at end of function");
|
||||||
#endif
|
|
||||||
if (global.params.useAssert &&
|
if (global.params.useAssert &&
|
||||||
!global.params.useInline)
|
!global.params.useInline)
|
||||||
{ /* Add an assert(0, msg); where the missing return
|
{ /* 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 = new AssignExp(Loc(), e1, e);
|
||||||
e->type = t;
|
e->type = t;
|
||||||
a->push(new ExpStatement(Loc(), e));
|
a->push(new ExpStatement(Loc(), e));
|
||||||
p->isargptr = TRUE;
|
p->isargptr = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1866,7 +1868,6 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fbody = new CompoundStatement(Loc(), a);
|
fbody = new CompoundStatement(Loc(), a);
|
||||||
#if DMDV2
|
|
||||||
/* Append destructor calls for parameters as finally blocks.
|
/* Append destructor calls for parameters as finally blocks.
|
||||||
*/
|
*/
|
||||||
if (parameters)
|
if (parameters)
|
||||||
@@ -1890,7 +1891,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
if (f->isnothrow && (global.errors != nothrowErrors) )
|
if (f->isnothrow && (global.errors != nothrowErrors) )
|
||||||
::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars());
|
::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars());
|
||||||
if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
|
if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
|
||||||
f->isnothrow = FALSE;
|
f->isnothrow = false;
|
||||||
if (fbody->blockExit(f->isnothrow) == BEfallthru)
|
if (fbody->blockExit(f->isnothrow) == BEfallthru)
|
||||||
fbody = new CompoundStatement(Loc(), fbody, s);
|
fbody = new CompoundStatement(Loc(), fbody, s);
|
||||||
else
|
else
|
||||||
@@ -1900,13 +1901,11 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
}
|
}
|
||||||
// from this point on all possible 'throwers' are checked
|
// from this point on all possible 'throwers' are checked
|
||||||
flags &= ~FUNCFLAGnothrowInprocess;
|
flags &= ~FUNCFLAGnothrowInprocess;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (isSynchronized())
|
if (isSynchronized())
|
||||||
{ /* Wrap the entire function body in a synchronized statement
|
{ /* Wrap the entire function body in a synchronized statement
|
||||||
*/
|
*/
|
||||||
AggregateDeclaration *ad = isThis();
|
ClassDeclaration *cd = isThis() ? isThis()->isClassDeclaration() : parent->isClassDeclaration();
|
||||||
ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration();
|
|
||||||
|
|
||||||
if (cd)
|
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->callSuper = 0;
|
||||||
sc2->pop();
|
sc2->pop();
|
||||||
}
|
}
|
||||||
@@ -1991,6 +1999,8 @@ void FuncDeclaration::semantic3(Scope *sc)
|
|||||||
semanticRun = PASSsemantic3done;
|
semanticRun = PASSsemantic3done;
|
||||||
semantic3Errors = global.errors - nerrors;
|
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());
|
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
|
||||||
//fflush(stdout);
|
//fflush(stdout);
|
||||||
}
|
}
|
||||||
@@ -2010,7 +2020,7 @@ bool FuncDeclaration::functionSemantic()
|
|||||||
semantic(scope);
|
semantic(scope);
|
||||||
global.gag = oldgag;
|
global.gag = oldgag;
|
||||||
if (spec && global.errors != olderrs)
|
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
|
if (olderrs != global.errors) // if errors compiling this function
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2060,7 +2070,7 @@ bool FuncDeclaration::functionSemantic3()
|
|||||||
// If it is a speculatively-instantiated template, and errors occur,
|
// If it is a speculatively-instantiated template, and errors occur,
|
||||||
// we need to mark the template as having errors.
|
// we need to mark the template as having errors.
|
||||||
if (spec && global.errors != olderrs)
|
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
|
if (olderrs != global.errors) // if errors compiling this function
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2074,9 +2084,9 @@ void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
|
|
||||||
StorageClassDeclaration::stcToCBuffer(buf, storage_class);
|
StorageClassDeclaration::stcToCBuffer(buf, storage_class);
|
||||||
type->toCBuffer(buf, ident, hgs);
|
type->toCBuffer(buf, ident, hgs);
|
||||||
if(hgs->hdrgen == 1)
|
if (hgs->hdrgen == 1)
|
||||||
{
|
{
|
||||||
if(storage_class & STCauto)
|
if (storage_class & STCauto)
|
||||||
{
|
{
|
||||||
hgs->autoMember++;
|
hgs->autoMember++;
|
||||||
bodyToCBuffer(buf, hgs);
|
bodyToCBuffer(buf, hgs);
|
||||||
@@ -2202,7 +2212,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
{
|
{
|
||||||
buf->writestring("out");
|
buf->writestring("out");
|
||||||
if (outId)
|
if (outId)
|
||||||
{ buf->writebyte('(');
|
{
|
||||||
|
buf->writebyte('(');
|
||||||
buf->writestring(outId->toChars());
|
buf->writestring(outId->toChars());
|
||||||
buf->writebyte(')');
|
buf->writebyte(')');
|
||||||
}
|
}
|
||||||
@@ -2228,7 +2239,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
hgs->autoMember = saveauto;
|
hgs->autoMember = saveauto;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ buf->writeByte(';');
|
{
|
||||||
|
buf->writeByte(';');
|
||||||
buf->writenl();
|
buf->writenl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2255,16 +2267,15 @@ void FuncDeclaration::buildResultVar()
|
|||||||
outId = Id::result; // provide a default
|
outId = Id::result; // provide a default
|
||||||
|
|
||||||
VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
|
VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL);
|
||||||
|
if (outId == Id::result) v->storage_class |= STCtemp;
|
||||||
v->noscope = 1;
|
v->noscope = 1;
|
||||||
v->storage_class |= STCresult;
|
v->storage_class |= STCresult;
|
||||||
#if DMDV2
|
|
||||||
if (!isVirtual())
|
if (!isVirtual())
|
||||||
v->storage_class |= STCconst;
|
v->storage_class |= STCconst;
|
||||||
if (tf->isref)
|
if (tf->isref)
|
||||||
{
|
{
|
||||||
v->storage_class |= STCref | STCforeach;
|
v->storage_class |= STCref | STCforeach;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
v->semantic(scout);
|
v->semantic(scout);
|
||||||
if (!scout->insert(v))
|
if (!scout->insert(v))
|
||||||
error("out result %s is already defined", v->toChars());
|
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);
|
ExpInitializer *ei = new ExpInitializer(Loc(), eresult);
|
||||||
VarDeclaration *v = new VarDeclaration(Loc(), t1, Lexer::uniqueId("__covres"), ei);
|
VarDeclaration *v = new VarDeclaration(Loc(), t1, Lexer::uniqueId("__covres"), ei);
|
||||||
|
v->storage_class |= STCtemp;
|
||||||
DeclarationExp *de = new DeclarationExp(Loc(), v);
|
DeclarationExp *de = new DeclarationExp(Loc(), v);
|
||||||
VarExp *ve = new VarExp(Loc(), v);
|
VarExp *ve = new VarExp(Loc(), v);
|
||||||
eresult = new CommaExp(Loc(), de, ve);
|
eresult = new CommaExp(Loc(), de, ve);
|
||||||
@@ -2578,6 +2590,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
|
|||||||
bool FuncDeclaration::overloadInsert(Dsymbol *s)
|
bool FuncDeclaration::overloadInsert(Dsymbol *s)
|
||||||
{
|
{
|
||||||
//printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
|
//printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
|
||||||
|
assert(s != this);
|
||||||
|
|
||||||
AliasDeclaration *ad = s->isAliasDeclaration();
|
AliasDeclaration *ad = s->isAliasDeclaration();
|
||||||
if (ad)
|
if (ad)
|
||||||
{
|
{
|
||||||
@@ -2598,7 +2612,7 @@ bool FuncDeclaration::overloadInsert(Dsymbol *s)
|
|||||||
if (overnext)
|
if (overnext)
|
||||||
return overnext->overloadInsert(td);
|
return overnext->overloadInsert(td);
|
||||||
overnext = td;
|
overnext = td;
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||||
if (!fd)
|
if (!fd)
|
||||||
@@ -2620,7 +2634,7 @@ bool FuncDeclaration::overloadInsert(Dsymbol *s)
|
|||||||
!isFuncAliasDeclaration())
|
!isFuncAliasDeclaration())
|
||||||
{
|
{
|
||||||
//printf("\tfalse: conflict %s\n", kind());
|
//printf("\tfalse: conflict %s\n", kind());
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2760,7 +2774,6 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
/* Allow covariant matches, as long as the return type
|
/* Allow covariant matches, as long as the return type
|
||||||
* is just a const conversion.
|
* is just a const conversion.
|
||||||
* This allows things like pure functions to match with an impure function type.
|
* This allows things like pure functions to match with an impure function type.
|
||||||
@@ -2774,7 +2787,6 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2788,7 +2800,7 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
|
|||||||
static void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod)
|
static void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod)
|
||||||
{
|
{
|
||||||
bool bothMutable = ((lhsMod & rhsMod) == 0);
|
bool bothMutable = ((lhsMod & rhsMod) == 0);
|
||||||
bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared);
|
bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared) != 0;
|
||||||
bool sharedMismatchOnly = ((lhsMod ^ rhsMod) == MODshared);
|
bool sharedMismatchOnly = ((lhsMod ^ rhsMod) == MODshared);
|
||||||
|
|
||||||
if (lhsMod & MODshared)
|
if (lhsMod & MODshared)
|
||||||
@@ -3006,7 +3018,6 @@ Lerror:
|
|||||||
if (tthis)
|
if (tthis)
|
||||||
tthis->modToBuffer(&fargsBuf);
|
tthis->modToBuffer(&fargsBuf);
|
||||||
|
|
||||||
assert(!m.lastf || m.nextf);
|
|
||||||
if (!m.lastf && !(flags & 1)) // no match
|
if (!m.lastf && !(flags & 1)) // no match
|
||||||
{
|
{
|
||||||
if (td)
|
if (td)
|
||||||
@@ -3202,12 +3213,17 @@ int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
|
|||||||
return level;
|
return level;
|
||||||
|
|
||||||
Lerr:
|
Lerr:
|
||||||
|
Dsymbol *p = toParent2();
|
||||||
|
while (p->toParent2()->isFuncDeclaration())
|
||||||
|
p = p->toParent2();
|
||||||
|
|
||||||
// Don't give error if in template constraint
|
// 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
|
// better diagnostics for static functions
|
||||||
::error(loc, "%s%s %s cannot access frame of function %s",
|
::error(loc, "%s%s %s cannot access frame of function %s",
|
||||||
isStatic() ? "static " : "", kind(), toPrettyChars(), fd->toPrettyChars());
|
xstatic, kind(), toPrettyChars(), fd->toPrettyChars());
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -3414,7 +3430,7 @@ PURE FuncDeclaration::isPureBypassingInference()
|
|||||||
/**************************************
|
/**************************************
|
||||||
* The function is doing something impure,
|
* The function is doing something impure,
|
||||||
* so mark it as 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()
|
bool FuncDeclaration::setImpure()
|
||||||
{
|
{
|
||||||
@@ -3423,8 +3439,8 @@ bool FuncDeclaration::setImpure()
|
|||||||
flags &= ~FUNCFLAGpurityInprocess;
|
flags &= ~FUNCFLAGpurityInprocess;
|
||||||
}
|
}
|
||||||
else if (isPure())
|
else if (isPure())
|
||||||
return TRUE;
|
return true;
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FuncDeclaration::isSafe()
|
bool FuncDeclaration::isSafe()
|
||||||
@@ -3454,7 +3470,7 @@ bool FuncDeclaration::isTrusted()
|
|||||||
/**************************************
|
/**************************************
|
||||||
* The function is doing something unsave,
|
* The function is doing something unsave,
|
||||||
* so mark it as unsafe.
|
* so mark it as unsafe.
|
||||||
* If there's a safe error, return TRUE.
|
* If there's a safe error, return true.
|
||||||
*/
|
*/
|
||||||
bool FuncDeclaration::setUnsafe()
|
bool FuncDeclaration::setUnsafe()
|
||||||
{
|
{
|
||||||
@@ -3464,8 +3480,8 @@ bool FuncDeclaration::setUnsafe()
|
|||||||
((TypeFunction *)type)->trust = TRUSTsystem;
|
((TypeFunction *)type)->trust = TRUSTsystem;
|
||||||
}
|
}
|
||||||
else if (isSafe())
|
else if (isSafe())
|
||||||
return TRUE;
|
return true;
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
@@ -3737,7 +3753,7 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
|
|||||||
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
|
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
|
||||||
|
|
||||||
//printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
|
//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());
|
//printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
|
||||||
|
|
||||||
if (fdv2 && fdthis && fdv2 != fdthis)
|
if (fdv2 && fdthis && fdv2 != fdthis)
|
||||||
@@ -3747,19 +3763,20 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
|
|||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; i < siblingCallers.dim; ++i)
|
for (int i = 0; i < siblingCallers.dim; ++i)
|
||||||
{ if (siblingCallers[i] == fdthis)
|
{
|
||||||
|
if (siblingCallers[i] == fdthis)
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
//printf("\tadding sibling %s\n", fdthis->toPrettyChars());
|
//printf("\tadding sibling %s\n", fdthis->toPrettyChars());
|
||||||
siblingCallers.push(fdthis);
|
if (!sc->intypeof && !(sc->flags & SCOPEcompile))
|
||||||
|
siblingCallers.push(fdthis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncDeclaration *fdv = toParent()->isFuncDeclaration();
|
FuncDeclaration *fdv = toParent2()->isFuncDeclaration();
|
||||||
fdv = toParent()->isFuncDeclaration();
|
|
||||||
if (fdv && fdthis && fdv != fdthis)
|
if (fdv && fdthis && fdv != fdthis)
|
||||||
{
|
{
|
||||||
int lv = fdthis->getLevel(loc, sc, fdv);
|
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
|
* Note that nested functions can only call lexically earlier nested
|
||||||
* functions, so loops are impossible.
|
* 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());
|
//printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars());
|
||||||
bool bAnyClosures = false;
|
bool bAnyClosures = false;
|
||||||
for (int i = 0; i < f->siblingCallers.dim; ++i)
|
for (int i = 0; i < f->siblingCallers.dim; ++i)
|
||||||
@@ -3818,7 +3845,19 @@ bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
|
|||||||
markAsNeedingClosure(g, outerFunc);
|
markAsNeedingClosure(g, outerFunc);
|
||||||
bAnyClosures = true;
|
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);
|
//printf("\t%d\n", bAnyClosures);
|
||||||
return bAnyClosures;
|
return bAnyClosures;
|
||||||
@@ -3831,7 +3870,6 @@ bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc)
|
|||||||
* created for them.
|
* created for them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
bool FuncDeclaration::needsClosure()
|
bool FuncDeclaration::needsClosure()
|
||||||
{
|
{
|
||||||
/* Need a closure for all the closureVars[] if any of the
|
/* Need a closure for all the closureVars[] if any of the
|
||||||
@@ -3926,7 +3964,6 @@ Lyes:
|
|||||||
//printf("\tneeds closure\n");
|
//printf("\tneeds closure\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/***********************************************
|
/***********************************************
|
||||||
* Determine if function's variables are referenced by a function
|
* Determine if function's variables are referenced by a function
|
||||||
@@ -3935,11 +3972,7 @@ Lyes:
|
|||||||
|
|
||||||
bool FuncDeclaration::hasNestedFrameRefs()
|
bool FuncDeclaration::hasNestedFrameRefs()
|
||||||
{
|
{
|
||||||
#if DMDV2
|
|
||||||
if (closureVars.dim)
|
if (closureVars.dim)
|
||||||
#else
|
|
||||||
if (nestedFrameRef)
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* If a virtual method has contracts, assume its variables are referenced
|
/* 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 ****************************/
|
/********************************* CtorDeclaration ****************************/
|
||||||
|
|
||||||
@@ -4167,7 +4210,7 @@ void CtorDeclaration::semantic(Scope *sc)
|
|||||||
storage_class |= STCdisable;
|
storage_class |= STCdisable;
|
||||||
fbody = NULL;
|
fbody = NULL;
|
||||||
}
|
}
|
||||||
sd->noDefaultCtor = TRUE;
|
sd->noDefaultCtor = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -4204,7 +4247,6 @@ bool CtorDeclaration::addPostInvariant()
|
|||||||
|
|
||||||
/********************************* PostBlitDeclaration ****************************/
|
/********************************* PostBlitDeclaration ****************************/
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
|
PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
|
||||||
: FuncDeclaration(loc, endloc, id, stc, NULL)
|
: FuncDeclaration(loc, endloc, id, stc, NULL)
|
||||||
{
|
{
|
||||||
@@ -4238,7 +4280,7 @@ void PostBlitDeclaration::semantic(Scope *sc)
|
|||||||
ad->postblits.push(this);
|
ad->postblits.push(this);
|
||||||
|
|
||||||
if (!type)
|
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 = sc->push();
|
||||||
sc->stc &= ~STCstatic; // not static
|
sc->stc &= ~STCstatic; // not static
|
||||||
@@ -4274,7 +4316,6 @@ void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring("this(this)");
|
buf->writestring("this(this)");
|
||||||
bodyToCBuffer(buf, hgs);
|
bodyToCBuffer(buf, hgs);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/********************************* DtorDeclaration ****************************/
|
/********************************* DtorDeclaration ****************************/
|
||||||
|
|
||||||
@@ -4318,7 +4359,7 @@ void DtorDeclaration::semantic(Scope *sc)
|
|||||||
ad->dtors.push(this);
|
ad->dtors.push(this);
|
||||||
|
|
||||||
if (!type)
|
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 = sc->push();
|
||||||
sc->stc &= ~STCstatic; // not a static destructor
|
sc->stc &= ~STCstatic; // not a static destructor
|
||||||
@@ -4398,7 +4439,7 @@ void StaticCtorDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!type)
|
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,
|
/* If the static ctor appears within a template instantiation,
|
||||||
* it could get called multiple times by the module constructors
|
* it could get called multiple times by the module constructors
|
||||||
@@ -4414,7 +4455,7 @@ void StaticCtorDeclaration::semantic(Scope *sc)
|
|||||||
*/
|
*/
|
||||||
Identifier *id = Lexer::idPool("__gate");
|
Identifier *id = Lexer::idPool("__gate");
|
||||||
VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL);
|
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();
|
Statements *sa = new Statements();
|
||||||
Statement *s = new ExpStatement(Loc(), v);
|
Statement *s = new ExpStatement(Loc(), v);
|
||||||
sa->push(s);
|
sa->push(s);
|
||||||
@@ -4452,7 +4493,7 @@ bool StaticCtorDeclaration::isVirtual()
|
|||||||
|
|
||||||
bool StaticCtorDeclaration::hasStaticCtorOrDtor()
|
bool StaticCtorDeclaration::hasStaticCtorOrDtor()
|
||||||
{
|
{
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StaticCtorDeclaration::addPreInvariant()
|
bool StaticCtorDeclaration::addPreInvariant()
|
||||||
@@ -4529,7 +4570,7 @@ void StaticDtorDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!type)
|
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,
|
/* If the static ctor appears within a template instantiation,
|
||||||
* it could get called multiple times by the module constructors
|
* it could get called multiple times by the module constructors
|
||||||
@@ -4546,7 +4587,7 @@ void StaticDtorDeclaration::semantic(Scope *sc)
|
|||||||
*/
|
*/
|
||||||
Identifier *id = Lexer::idPool("__gate");
|
Identifier *id = Lexer::idPool("__gate");
|
||||||
VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL);
|
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();
|
Statements *sa = new Statements();
|
||||||
Statement *s = new ExpStatement(Loc(), v);
|
Statement *s = new ExpStatement(Loc(), v);
|
||||||
sa->push(s);
|
sa->push(s);
|
||||||
@@ -4585,7 +4626,7 @@ bool StaticDtorDeclaration::isVirtual()
|
|||||||
|
|
||||||
bool StaticDtorDeclaration::hasStaticCtorOrDtor()
|
bool StaticDtorDeclaration::hasStaticCtorOrDtor()
|
||||||
{
|
{
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StaticDtorDeclaration::addPreInvariant()
|
bool StaticDtorDeclaration::addPreInvariant()
|
||||||
@@ -4669,7 +4710,7 @@ void InvariantDeclaration::semantic(Scope *sc)
|
|||||||
ad->invs.push(this);
|
ad->invs.push(this);
|
||||||
}
|
}
|
||||||
if (!type)
|
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 = sc->push();
|
||||||
sc->stc &= ~STCstatic; // not a static invariant
|
sc->stc &= ~STCstatic; // not a static invariant
|
||||||
@@ -4752,7 +4793,7 @@ void UnitTestDeclaration::semantic(Scope *sc)
|
|||||||
if (global.params.useUnitTests)
|
if (global.params.useUnitTests)
|
||||||
{
|
{
|
||||||
if (!type)
|
if (!type)
|
||||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
type = new TypeFunction(NULL, Type::tvoid, false, LINKd);
|
||||||
Scope *sc2 = sc->push();
|
Scope *sc2 = sc->push();
|
||||||
sc2->linkage = LINKd;
|
sc2->linkage = LINKd;
|
||||||
FuncDeclaration::semantic(sc2);
|
FuncDeclaration::semantic(sc2);
|
||||||
|
|||||||
@@ -18,9 +18,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#if __DMC__
|
|
||||||
#include <complex.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,6 @@ Identifier::Identifier(const char *string, int value)
|
|||||||
this->len = strlen(string);
|
this->len = strlen(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_t Identifier::hashCode()
|
|
||||||
{
|
|
||||||
return String::calcHash(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Identifier::equals(RootObject *o)
|
bool Identifier::equals(RootObject *o)
|
||||||
{
|
{
|
||||||
#if IN_LLVM // ASan
|
#if IN_LLVM // ASan
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ public:
|
|||||||
|
|
||||||
Identifier(const char *string, int value);
|
Identifier(const char *string, int value);
|
||||||
bool equals(RootObject *o);
|
bool equals(RootObject *o);
|
||||||
hash_t hashCode();
|
|
||||||
int compare(RootObject *o);
|
int compare(RootObject *o);
|
||||||
void print();
|
void print();
|
||||||
char *toChars();
|
char *toChars();
|
||||||
|
|||||||
+1
-4
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2012 by Digital Mars
|
// Copyright (c) 1999-2013 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -405,9 +405,6 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "// File generated by idgen.c\n");
|
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, "#ifndef DMD_ID_H\n");
|
||||||
fprintf(fp, "#define DMD_ID_H 1\n");
|
fprintf(fp, "#define DMD_ID_H 1\n");
|
||||||
fprintf(fp, "class Identifier;\n");
|
fprintf(fp, "class Identifier;\n");
|
||||||
|
|||||||
@@ -27,21 +27,6 @@
|
|||||||
|
|
||||||
const char *importHint(const char *s)
|
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[] =
|
static const char *modules[] =
|
||||||
{ "core.stdc.stdio",
|
{ "core.stdc.stdio",
|
||||||
"std.stdio",
|
"std.stdio",
|
||||||
@@ -55,7 +40,6 @@ const char *importHint(const char *s)
|
|||||||
"sin", "cos", "sqrt", "fabs", NULL,
|
"sin", "cos", "sqrt", "fabs", NULL,
|
||||||
"__va_argsave_t", NULL,
|
"__va_argsave_t", NULL,
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++)
|
for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -289,7 +289,7 @@ void Import::semantic(Scope *sc)
|
|||||||
* ModuleAliasIdentifier ] "\n"
|
* ModuleAliasIdentifier ] "\n"
|
||||||
*
|
*
|
||||||
* BasicImportDeclaration
|
* BasicImportDeclaration
|
||||||
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection
|
* ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
|
||||||
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
|
* " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
|
||||||
*
|
*
|
||||||
* FilePath
|
* FilePath
|
||||||
|
|||||||
+25
-15
@@ -287,13 +287,14 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
|
|||||||
ExpInitializer *ie = new ExpInitializer(loc, e);
|
ExpInitializer *ie = new ExpInitializer(loc, e);
|
||||||
return ie->semantic(sc, t, needInterpret);
|
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 { }
|
/* Rewrite as empty delegate literal { }
|
||||||
*/
|
*/
|
||||||
Parameters *arguments = new Parameters;
|
Parameters *arguments = new Parameters;
|
||||||
Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
|
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->fbody = new CompoundStatement(loc, new Statements());
|
||||||
fd->endloc = loc;
|
fd->endloc = loc;
|
||||||
Expression *e = new FuncExp(loc, fd);
|
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
|
if (sem) // if semantic() already run
|
||||||
return this;
|
return this;
|
||||||
sem = 1;
|
sem = 1;
|
||||||
type = t;
|
|
||||||
Initializer *aa = NULL;
|
|
||||||
t = t->toBasetype();
|
t = t->toBasetype();
|
||||||
switch (t->ty)
|
switch (t->ty)
|
||||||
{
|
{
|
||||||
case Tpointer:
|
|
||||||
case Tsarray:
|
case Tsarray:
|
||||||
case Tarray:
|
case Tarray:
|
||||||
break;
|
break;
|
||||||
@@ -402,15 +400,27 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Taarray:
|
case Taarray:
|
||||||
// was actually an associative array literal
|
case Tstruct: // consider implicit constructor call
|
||||||
aa = new ExpInitializer(loc, toAssocArrayLiteral());
|
{
|
||||||
return aa->semantic(sc, t, needInterpret);
|
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:
|
default:
|
||||||
error(loc, "cannot use array to initialize %s", type->toChars());
|
error(loc, "cannot use array to initialize %s", t->toChars());
|
||||||
goto Lerr;
|
goto Lerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type = t;
|
||||||
|
|
||||||
length = 0;
|
length = 0;
|
||||||
for (size_t i = 0; i < index.dim; i++)
|
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();
|
sc = sc->endCTFE();
|
||||||
idx = idx->ctfeInterpret();
|
idx = idx->ctfeInterpret();
|
||||||
index[i] = idx;
|
index[i] = idx;
|
||||||
length = idx->toInteger();
|
length = (size_t)idx->toInteger();
|
||||||
if (idx->op == TOKerror)
|
if (idx->op == TOKerror)
|
||||||
errors = true;
|
errors = true;
|
||||||
}
|
}
|
||||||
@@ -509,7 +519,7 @@ Expression *ArrayInitializer::toExpression(Type *tx)
|
|||||||
switch (t->ty)
|
switch (t->ty)
|
||||||
{
|
{
|
||||||
case Tsarray:
|
case Tsarray:
|
||||||
edim = ((TypeSArray *)t)->dim->toInteger();
|
edim = (size_t)((TypeSArray *)t)->dim->toInteger();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Tpointer:
|
case Tpointer:
|
||||||
@@ -529,7 +539,7 @@ Expression *ArrayInitializer::toExpression(Type *tx)
|
|||||||
if (index[i])
|
if (index[i])
|
||||||
{
|
{
|
||||||
if (index[i]->op == TOKint64)
|
if (index[i]->op == TOKint64)
|
||||||
j = index[i]->toInteger();
|
j = (size_t)index[i]->toInteger();
|
||||||
else
|
else
|
||||||
goto Lno;
|
goto Lno;
|
||||||
}
|
}
|
||||||
@@ -544,7 +554,7 @@ Expression *ArrayInitializer::toExpression(Type *tx)
|
|||||||
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
|
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
|
||||||
{
|
{
|
||||||
if (index[i])
|
if (index[i])
|
||||||
j = (index[i])->toInteger();
|
j = (size_t)(index[i])->toInteger();
|
||||||
assert(j < edim);
|
assert(j < edim);
|
||||||
Initializer *iz = value[i];
|
Initializer *iz = value[i];
|
||||||
if (!iz)
|
if (!iz)
|
||||||
@@ -808,7 +818,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
|
|||||||
exp = resolveProperties(sc, exp);
|
exp = resolveProperties(sc, exp);
|
||||||
if (needInterpret) sc = sc->endCTFE();
|
if (needInterpret) sc = sc->endCTFE();
|
||||||
if (exp->op == TOKerror)
|
if (exp->op == TOKerror)
|
||||||
return this;
|
return new ErrorInitializer();
|
||||||
|
|
||||||
int olderrors = global.errors;
|
int olderrors = global.errors;
|
||||||
if (needInterpret)
|
if (needInterpret)
|
||||||
@@ -966,7 +976,7 @@ Expression *ExpInitializer::toExpression(Type *t)
|
|||||||
if (tb->ty == Tsarray && exp->implicitConvTo(tb->nextOf()))
|
if (tb->ty == Tsarray && exp->implicitConvTo(tb->nextOf()))
|
||||||
{
|
{
|
||||||
TypeSArray *tsa = (TypeSArray *)tb;
|
TypeSArray *tsa = (TypeSArray *)tb;
|
||||||
size_t d = tsa->dim->toInteger();
|
size_t d = (size_t)tsa->dim->toInteger();
|
||||||
Expressions *elements = new Expressions();
|
Expressions *elements = new Expressions();
|
||||||
elements->setDim(d);
|
elements->setDim(d);
|
||||||
for (size_t i = 0; i < d; i++)
|
for (size_t i = 0; i < d; i++)
|
||||||
|
|||||||
+237
-152
@@ -156,12 +156,10 @@ int ReturnStatement::inlineCost(InlineCostState *ics)
|
|||||||
return expressionInlineCost(exp, ics);
|
return expressionInlineCost(exp, ics);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
int ImportStatement::inlineCost(InlineCostState *ics)
|
int ImportStatement::inlineCost(InlineCostState *ics)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int ForStatement::inlineCost(InlineCostState *ics)
|
int ForStatement::inlineCost(InlineCostState *ics)
|
||||||
{
|
{
|
||||||
@@ -253,10 +251,8 @@ int ThisExp::inlineCost3(InlineCostState *ics)
|
|||||||
int StructLiteralExp::inlineCost3(InlineCostState *ics)
|
int StructLiteralExp::inlineCost3(InlineCostState *ics)
|
||||||
{
|
{
|
||||||
//printf("StructLiteralExp::inlineCost3() %s\n", toChars());
|
//printf("StructLiteralExp::inlineCost3() %s\n", toChars());
|
||||||
#if DMDV2
|
|
||||||
if (sd->isNested())
|
if (sd->isNested())
|
||||||
return COST_MAX;
|
return COST_MAX;
|
||||||
#endif
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,10 +305,8 @@ int DeclarationExp::inlineCost3(InlineCostState *ics)
|
|||||||
return COST_MAX;
|
return COST_MAX;
|
||||||
cost += 1;
|
cost += 1;
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (vd->edtor) // if destructor required
|
if (vd->edtor) // if destructor required
|
||||||
return COST_MAX; // needs work to make this work
|
return COST_MAX; // needs work to make this work
|
||||||
#endif
|
|
||||||
// Scan initializer (vd->init)
|
// Scan initializer (vd->init)
|
||||||
if (vd->init)
|
if (vd->init)
|
||||||
{
|
{
|
||||||
@@ -332,9 +326,7 @@ int DeclarationExp::inlineCost3(InlineCostState *ics)
|
|||||||
declaration->isClassDeclaration() ||
|
declaration->isClassDeclaration() ||
|
||||||
declaration->isFuncDeclaration() ||
|
declaration->isFuncDeclaration() ||
|
||||||
declaration->isTypedefDeclaration() ||
|
declaration->isTypedefDeclaration() ||
|
||||||
#if DMDV2
|
|
||||||
declaration->isAttribDeclaration() ||
|
declaration->isAttribDeclaration() ||
|
||||||
#endif
|
|
||||||
declaration->isTemplateMixin())
|
declaration->isTemplateMixin())
|
||||||
return COST_MAX;
|
return COST_MAX;
|
||||||
|
|
||||||
@@ -364,13 +356,15 @@ int CallExp::inlineCost3(InlineCostState *ics)
|
|||||||
|
|
||||||
struct InlineDoState
|
struct InlineDoState
|
||||||
{
|
{
|
||||||
|
// inline context
|
||||||
VarDeclaration *vthis;
|
VarDeclaration *vthis;
|
||||||
Dsymbols from; // old Dsymbols
|
Dsymbols from; // old Dsymbols
|
||||||
Dsymbols to; // parallel array of new Dsymbols
|
Dsymbols to; // parallel array of new Dsymbols
|
||||||
Dsymbol *parent; // new parent
|
Dsymbol *parent; // new parent
|
||||||
FuncDeclaration *fd; // function being inlined (old parent)
|
FuncDeclaration *fd; // function being inlined (old parent)
|
||||||
|
// inline result
|
||||||
|
bool foundReturn;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
Statement *Statement::doInlineStatement(InlineDoState *ids)
|
Statement *Statement::doInlineStatement(InlineDoState *ids)
|
||||||
@@ -397,20 +391,7 @@ Statement *CompoundStatement::doInlineStatement(InlineDoState *ids)
|
|||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
as->push(s->doInlineStatement(ids));
|
as->push(s->doInlineStatement(ids));
|
||||||
if (s->isReturnStatement())
|
if (ids->foundReturn)
|
||||||
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()
|
|
||||||
)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -429,7 +410,7 @@ Statement *UnrolledLoopStatement::doInlineStatement(InlineDoState *ids)
|
|||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
as->push(s->doInlineStatement(ids));
|
as->push(s->doInlineStatement(ids));
|
||||||
if (s->isReturnStatement())
|
if (ids->foundReturn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -450,7 +431,11 @@ Statement *IfStatement::doInlineStatement(InlineDoState *ids)
|
|||||||
|
|
||||||
Expression *condition = this->condition ? this->condition->doInline(ids) : NULL;
|
Expression *condition = this->condition ? this->condition->doInline(ids) : NULL;
|
||||||
Statement *ifbody = this->ifbody ? this->ifbody->doInlineStatement(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;
|
Statement *elsebody = this->elsebody ? this->elsebody->doInlineStatement(ids) : NULL;
|
||||||
|
ids->foundReturn = ids->foundReturn && bodyReturn;
|
||||||
|
|
||||||
|
|
||||||
return new IfStatement(loc, arg, condition, ifbody, elsebody);
|
return new IfStatement(loc, arg, condition, ifbody, elsebody);
|
||||||
}
|
}
|
||||||
@@ -458,15 +443,14 @@ Statement *IfStatement::doInlineStatement(InlineDoState *ids)
|
|||||||
Statement *ReturnStatement::doInlineStatement(InlineDoState *ids)
|
Statement *ReturnStatement::doInlineStatement(InlineDoState *ids)
|
||||||
{
|
{
|
||||||
//printf("ReturnStatement::doInlineStatement() '%s'\n", exp ? exp->toChars() : "");
|
//printf("ReturnStatement::doInlineStatement() '%s'\n", exp ? exp->toChars() : "");
|
||||||
|
ids->foundReturn = true;
|
||||||
return new ReturnStatement(loc, exp ? exp->doInline(ids) : NULL);
|
return new ReturnStatement(loc, exp ? exp->doInline(ids) : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
Statement *ImportStatement::doInlineStatement(InlineDoState *ids)
|
Statement *ImportStatement::doInlineStatement(InlineDoState *ids)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Statement *ForStatement::doInlineStatement(InlineDoState *ids)
|
Statement *ForStatement::doInlineStatement(InlineDoState *ids)
|
||||||
{
|
{
|
||||||
@@ -507,20 +491,7 @@ Expression *CompoundStatement::doInline(InlineDoState *ids)
|
|||||||
{
|
{
|
||||||
Expression *e2 = s->doInline(ids);
|
Expression *e2 = s->doInline(ids);
|
||||||
e = Expression::combine(e, e2);
|
e = Expression::combine(e, e2);
|
||||||
if (s->isReturnStatement())
|
if (ids->foundReturn)
|
||||||
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()
|
|
||||||
)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -539,7 +510,7 @@ Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
|
|||||||
{
|
{
|
||||||
Expression *e2 = s->doInline(ids);
|
Expression *e2 = s->doInline(ids);
|
||||||
e = Expression::combine(e, e2);
|
e = Expression::combine(e, e2);
|
||||||
if (s->isReturnStatement())
|
if (ids->foundReturn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,9 +533,13 @@ Expression *IfStatement::doInline(InlineDoState *ids)
|
|||||||
econd = condition->doInline(ids);
|
econd = condition->doInline(ids);
|
||||||
assert(econd);
|
assert(econd);
|
||||||
if (ifbody)
|
if (ifbody)
|
||||||
|
{
|
||||||
e1 = ifbody->doInline(ids);
|
e1 = ifbody->doInline(ids);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
e1 = NULL;
|
e1 = NULL;
|
||||||
|
bool bodyReturn = ids->foundReturn;
|
||||||
|
ids->foundReturn = false;
|
||||||
if (elsebody)
|
if (elsebody)
|
||||||
e2 = elsebody->doInline(ids);
|
e2 = elsebody->doInline(ids);
|
||||||
else
|
else
|
||||||
@@ -573,6 +548,12 @@ Expression *IfStatement::doInline(InlineDoState *ids)
|
|||||||
{
|
{
|
||||||
e = new CondExp(econd->loc, econd, e1, e2);
|
e = new CondExp(econd->loc, econd, e1, e2);
|
||||||
e->type = e1->type;
|
e->type = e1->type;
|
||||||
|
if (e->type->ty == Ttuple)
|
||||||
|
{
|
||||||
|
e1->type = Type::tvoid;
|
||||||
|
e2->type = Type::tvoid;
|
||||||
|
e->type = Type::tvoid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (e1)
|
else if (e1)
|
||||||
{
|
{
|
||||||
@@ -588,21 +569,21 @@ Expression *IfStatement::doInline(InlineDoState *ids)
|
|||||||
{
|
{
|
||||||
e = econd;
|
e = econd;
|
||||||
}
|
}
|
||||||
|
ids->foundReturn = ids->foundReturn && bodyReturn;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *ReturnStatement::doInline(InlineDoState *ids)
|
Expression *ReturnStatement::doInline(InlineDoState *ids)
|
||||||
{
|
{
|
||||||
//printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
|
//printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
|
||||||
|
ids->foundReturn = true;
|
||||||
return exp ? exp->doInline(ids) : NULL;
|
return exp ? exp->doInline(ids) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
Expression *ImportStatement::doInline(InlineDoState *ids)
|
Expression *ImportStatement::doInline(InlineDoState *ids)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------- */
|
/* --------------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -643,7 +624,6 @@ Expression *SymOffExp::doInline(InlineDoState *ids)
|
|||||||
if (var == ids->from[i])
|
if (var == ids->from[i])
|
||||||
{
|
{
|
||||||
SymOffExp *se = (SymOffExp *)copy();
|
SymOffExp *se = (SymOffExp *)copy();
|
||||||
|
|
||||||
se->var = (Declaration *)ids->to[i];
|
se->var = (Declaration *)ids->to[i];
|
||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
@@ -659,7 +639,6 @@ Expression *VarExp::doInline(InlineDoState *ids)
|
|||||||
if (var == ids->from[i])
|
if (var == ids->from[i])
|
||||||
{
|
{
|
||||||
VarExp *ve = (VarExp *)copy();
|
VarExp *ve = (VarExp *)copy();
|
||||||
|
|
||||||
ve->var = (Declaration *)ids->to[i];
|
ve->var = (Declaration *)ids->to[i];
|
||||||
return ve;
|
return ve;
|
||||||
}
|
}
|
||||||
@@ -755,11 +734,9 @@ Expression *SuperExp::doInline(InlineDoState *ids)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expression *DeclarationExp::doInline(InlineDoState *ids)
|
Expression *DeclarationExp::doInline(InlineDoState *ids)
|
||||||
{ DeclarationExp *de = (DeclarationExp *)copy();
|
{
|
||||||
VarDeclaration *vd;
|
|
||||||
|
|
||||||
//printf("DeclarationExp::doInline(%s)\n", toChars());
|
//printf("DeclarationExp::doInline(%s)\n", toChars());
|
||||||
vd = declaration->isVarDeclaration();
|
VarDeclaration *vd = declaration->isVarDeclaration();
|
||||||
if (vd)
|
if (vd)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -780,9 +757,33 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
VarDeclaration *vto;
|
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);
|
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;
|
vto->parent = ids->parent;
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
vto->csym = NULL;
|
vto->csym = NULL;
|
||||||
@@ -792,6 +793,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
|
|||||||
ids->from.push(vd);
|
ids->from.push(vd);
|
||||||
ids->to.push(vto);
|
ids->to.push(vto);
|
||||||
|
|
||||||
|
L1:
|
||||||
if (vd->init)
|
if (vd->init)
|
||||||
{
|
{
|
||||||
if (vd->init->isVoidInitializer())
|
if (vd->init->isVoidInitializer())
|
||||||
@@ -805,13 +807,15 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
|
|||||||
vto->init = new ExpInitializer(e->loc, e->doInline(ids));
|
vto->init = new ExpInitializer(e->loc, e->doInline(ids));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DeclarationExp *de = (DeclarationExp *)copy();
|
||||||
de->declaration = (Dsymbol *) (void *)vto;
|
de->declaration = (Dsymbol *) (void *)vto;
|
||||||
|
return de;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* This needs work, like DeclarationExp::toElem(), if we are
|
/* This needs work, like DeclarationExp::toElem(), if we are
|
||||||
* to handle TemplateMixin's. For now, we just don't inline them.
|
* to handle TemplateMixin's. For now, we just don't inline them.
|
||||||
*/
|
*/
|
||||||
return de;
|
return Expression::doInline(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *NewExp::doInline(InlineDoState *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))
|
if (fd && fd != iss->fd && fd->canInline(0, 0, 1))
|
||||||
{
|
{
|
||||||
Statement *s;
|
Statement *s;
|
||||||
fd->expandInline(iss, NULL, ce->arguments, &s);
|
fd->expandInline(iss, NULL, NULL, ce->arguments, &s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1126,7 +1130,6 @@ Statement *ForeachStatement::inlineScan(InlineScanState *iss)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
|
Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
|
||||||
{
|
{
|
||||||
lwr = lwr->inlineScan(iss);
|
lwr = lwr->inlineScan(iss);
|
||||||
@@ -1135,7 +1138,6 @@ Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss)
|
|||||||
body = body->inlineScan(iss);
|
body = body->inlineScan(iss);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
Statement *IfStatement::inlineScan(InlineScanState *iss)
|
Statement *IfStatement::inlineScan(InlineScanState *iss)
|
||||||
@@ -1281,7 +1283,7 @@ Expression *Expression::inlineScan(InlineScanState *iss)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scanVar(Dsymbol *s, InlineScanState *iss)
|
Expression *scanVar(Dsymbol *s, InlineScanState *iss)
|
||||||
{
|
{
|
||||||
//printf("scanVar(%s %s)\n", s->kind(), s->toPrettyChars());
|
//printf("scanVar(%s %s)\n", s->kind(), s->toPrettyChars());
|
||||||
VarDeclaration *vd = s->isVarDeclaration();
|
VarDeclaration *vd = s->isVarDeclaration();
|
||||||
@@ -1291,47 +1293,20 @@ void scanVar(Dsymbol *s, InlineScanState *iss)
|
|||||||
if (td)
|
if (td)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < td->objects->dim; i++)
|
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);
|
assert(se->op == TOKdsymbol);
|
||||||
scanVar(se->s, iss);
|
scanVar(se->s, iss); // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (vd->init)
|
||||||
{
|
{
|
||||||
// Scan initializer (vd->init)
|
if (ExpInitializer *ie = vd->init->isExpInitializer())
|
||||||
if (vd->init)
|
|
||||||
{
|
{
|
||||||
ExpInitializer *ie = vd->init->isExpInitializer();
|
Expression *e = ie->exp->inlineScan(iss);
|
||||||
|
if (vd->init != ie) // DeclareExp with vd appears in e
|
||||||
if (ie)
|
return e;
|
||||||
{
|
ie->exp = e;
|
||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1339,13 +1314,14 @@ void scanVar(Dsymbol *s, InlineScanState *iss)
|
|||||||
{
|
{
|
||||||
s->inlineScan();
|
s->inlineScan();
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *DeclarationExp::inlineScan(InlineScanState *iss)
|
Expression *DeclarationExp::inlineScan(InlineScanState *iss)
|
||||||
{
|
{
|
||||||
//printf("DeclarationExp::inlineScan()\n");
|
//printf("DeclarationExp::inlineScan()\n");
|
||||||
scanVar(declaration, iss);
|
Expression *e = scanVar(declaration, iss);
|
||||||
return this;
|
return e ? e : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *UnaExp::inlineScan(InlineScanState *iss)
|
Expression *UnaExp::inlineScan(InlineScanState *iss)
|
||||||
@@ -1369,9 +1345,51 @@ Expression *BinExp::inlineScan(InlineScanState *iss)
|
|||||||
return this;
|
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 *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");
|
//printf("CallExp::inlineScan()\n");
|
||||||
e1 = e1->inlineScan(iss);
|
e1 = e1->inlineScan(iss);
|
||||||
@@ -1384,7 +1402,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
|
|||||||
|
|
||||||
if (fd && fd != iss->fd && fd->canInline(0, 0, 0))
|
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)
|
else if (e1->op == TOKdotvar)
|
||||||
@@ -1404,10 +1422,12 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
else
|
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;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1680,12 +1700,13 @@ Lno:
|
|||||||
return 0;
|
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;
|
InlineDoState ids;
|
||||||
DeclarationExp *de;
|
|
||||||
Expression *e = NULL;
|
Expression *e = NULL;
|
||||||
Statements *as = NULL;
|
Statements *as = NULL;
|
||||||
|
TypeFunction *tf = (TypeFunction*)type;
|
||||||
|
|
||||||
#if LOG || CANINLINE_LOG
|
#if LOG || CANINLINE_LOG
|
||||||
printf("FuncDeclaration::expandInline('%s')\n", toChars());
|
printf("FuncDeclaration::expandInline('%s')\n", toChars());
|
||||||
@@ -1698,6 +1719,38 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
|||||||
if (ps)
|
if (ps)
|
||||||
as = new Statements();
|
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
|
// Set up vthis
|
||||||
if (ethis)
|
if (ethis)
|
||||||
{
|
{
|
||||||
@@ -1737,12 +1790,31 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
|||||||
// Set up parameters
|
// Set up parameters
|
||||||
if (ethis)
|
if (ethis)
|
||||||
{
|
{
|
||||||
e = new DeclarationExp(Loc(), ids.vthis);
|
Expression *de = new DeclarationExp(Loc(), ids.vthis);
|
||||||
e->type = Type::tvoid;
|
de->type = Type::tvoid;
|
||||||
if (as)
|
e = Expression::combine(e, de);
|
||||||
as->push(new ExpStatement(e->loc, e));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
if (arguments && arguments->dim)
|
||||||
{
|
{
|
||||||
assert(parameters->dim == arguments->dim);
|
assert(parameters->dim == arguments->dim);
|
||||||
@@ -1758,7 +1830,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
|||||||
ei = new ExpInitializer(arg->loc, arg);
|
ei = new ExpInitializer(arg->loc, arg);
|
||||||
|
|
||||||
vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
|
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->linkage = vfrom->linkage;
|
||||||
vto->parent = iss->fd;
|
vto->parent = iss->fd;
|
||||||
//printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
|
//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 = new ConstructExp(vto->loc, ve, arg);
|
||||||
ei->exp->type = ve->type;
|
ei->exp->type = ve->type;
|
||||||
//ve->type->print();
|
//ve->type->print();
|
||||||
//arg->type->print();
|
//arg->type->print();
|
||||||
//ei->exp->print();
|
//ei->exp->print();
|
||||||
|
|
||||||
ids.from.push(vfrom);
|
ids.from.push(vfrom);
|
||||||
ids.to.push(vto);
|
ids.to.push(vto);
|
||||||
|
|
||||||
de = new DeclarationExp(Loc(), vto);
|
DeclarationExp *de = new DeclarationExp(Loc(), vto);
|
||||||
de->type = Type::tvoid;
|
de->type = Type::tvoid;
|
||||||
|
|
||||||
if (as)
|
e = Expression::combine(e, de);
|
||||||
as->push(new ExpStatement(Loc(), de));
|
|
||||||
else
|
|
||||||
e = Expression::combine(e, de);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps)
|
if (ps)
|
||||||
{
|
{
|
||||||
|
if (e)
|
||||||
|
as->push(new ExpStatement(Loc(), e));
|
||||||
inlineNest++;
|
inlineNest++;
|
||||||
Statement *s = fbody->doInlineStatement(&ids);
|
Statement *s = fbody->doInlineStatement(&ids);
|
||||||
as->push(s);
|
as->push(s);
|
||||||
@@ -1804,55 +1875,69 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
|||||||
//eb->type->print();
|
//eb->type->print();
|
||||||
//eb->print();
|
//eb->print();
|
||||||
//eb->dump(0);
|
//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());
|
//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
|
// Need to reevaluate whether parent can now be inlined
|
||||||
// in expressions, as we might have inlined statements
|
// in expressions, as we might have inlined statements
|
||||||
iss->fd->inlineStatusExp = ILSuninitialized;
|
iss->fd->inlineStatusExp = ILSuninitialized;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnitTestDeclaration::inlineScan()
|
||||||
|
{
|
||||||
|
if (global.params.useUnitTests)
|
||||||
|
{
|
||||||
|
FuncDeclaration::inlineScan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Perform the "inline copying" of a default argument for a function parameter.
|
* Perform the "inline copying" of a default argument for a function parameter.
|
||||||
|
|||||||
+207
-85
@@ -306,7 +306,7 @@ int CompiledCtfeFunction::walkAllVars(Expression *e, void *_this)
|
|||||||
if (global.gag && ccf->func)
|
if (global.gag && ccf->func)
|
||||||
return 1;
|
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);
|
assert(0);
|
||||||
}
|
}
|
||||||
if (e->op == TOKdeclaration)
|
if (e->op == TOKdeclaration)
|
||||||
@@ -570,11 +570,7 @@ void TryCatchStatement::ctfeCompile(CompiledCtfeFunction *ccf)
|
|||||||
body->ctfeCompile(ccf);
|
body->ctfeCompile(ccf);
|
||||||
for (size_t i = 0; i < catches->dim; i++)
|
for (size_t i = 0; i < catches->dim; i++)
|
||||||
{
|
{
|
||||||
#if DMDV1
|
Catch *ca = (*catches)[i];
|
||||||
Catch *ca = (Catch *)catches->data[i];
|
|
||||||
#else
|
|
||||||
Catch *ca = catches->tdata()[i];
|
|
||||||
#endif
|
|
||||||
if (ca->var)
|
if (ca->var)
|
||||||
ccf->onDeclaration(ca->var);
|
ccf->onDeclaration(ca->var);
|
||||||
if (ca->handler)
|
if (ca->handler)
|
||||||
@@ -958,6 +954,12 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
|||||||
#endif
|
#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
|
/* This is how we deal with a recursive statement AST
|
||||||
* that has arbitrary goto statements in it.
|
* that has arbitrary goto statements in it.
|
||||||
* Bubble up a 'result' which is the target of the goto
|
* Bubble up a 'result' which is the target of the goto
|
||||||
@@ -1001,13 +1003,6 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
|||||||
|
|
||||||
/******************************** Statement ***************************/
|
/******************************** Statement ***************************/
|
||||||
|
|
||||||
#define START() \
|
|
||||||
if (istate->start) \
|
|
||||||
{ if (istate->start != this) \
|
|
||||||
return NULL; \
|
|
||||||
istate->start = NULL; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* Interpret the statement.
|
* Interpret the statement.
|
||||||
* Returns:
|
* Returns:
|
||||||
@@ -1021,7 +1016,12 @@ Expression *Statement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s Statement::interpret()\n", loc.toChars());
|
printf("%s Statement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#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());
|
error("Statement %s cannot be interpreted at compile time", this->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
@@ -1031,7 +1031,12 @@ Expression *ExpStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s ExpStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : "");
|
printf("%s ExpStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : "");
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (exp)
|
if (exp)
|
||||||
{
|
{
|
||||||
Expression *e = exp->interpret(istate, ctfeNeedNothing);
|
Expression *e = exp->interpret(istate, ctfeNeedNothing);
|
||||||
@@ -1140,7 +1145,7 @@ Expression *IfStatement::interpret(InterState *istate)
|
|||||||
{
|
{
|
||||||
if (isTrueBool(e))
|
if (isTrueBool(e))
|
||||||
e = ifbody ? ifbody->interpret(istate) : NULL;
|
e = ifbody ? ifbody->interpret(istate) : NULL;
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
e = elsebody ? elsebody->interpret(istate) : NULL;
|
e = elsebody ? elsebody->interpret(istate) : NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1349,7 +1354,12 @@ Expression *ReturnStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s ReturnStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : "");
|
printf("%s ReturnStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : "");
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!exp)
|
if (!exp)
|
||||||
return EXP_VOID_INTERPRET;
|
return EXP_VOID_INTERPRET;
|
||||||
assert(istate && istate->fd && istate->fd->type);
|
assert(istate && istate->fd && istate->fd->type);
|
||||||
@@ -1410,7 +1420,12 @@ Expression *BreakStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s BreakStatement::interpret()\n", loc.toChars());
|
printf("%s BreakStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ident)
|
if (ident)
|
||||||
{
|
{
|
||||||
LabelDsymbol *label = istate->fd->searchLabel(ident);
|
LabelDsymbol *label = istate->fd->searchLabel(ident);
|
||||||
@@ -1440,7 +1455,12 @@ Expression *ContinueStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s ContinueStatement::interpret()\n", loc.toChars());
|
printf("%s ContinueStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ident)
|
if (ident)
|
||||||
{
|
{
|
||||||
LabelDsymbol *label = istate->fd->searchLabel(ident);
|
LabelDsymbol *label = istate->fd->searchLabel(ident);
|
||||||
@@ -1513,7 +1533,7 @@ Expression *DoStatement::interpret(InterState *istate)
|
|||||||
if (isTrueBool(e))
|
if (isTrueBool(e))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
{ e = NULL;
|
{ e = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1550,7 +1570,7 @@ Expression *ForStatement::interpret(InterState *istate)
|
|||||||
{ e = EXP_CANT_INTERPRET;
|
{ e = EXP_CANT_INTERPRET;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (e->isBool(FALSE))
|
if (e->isBool(false))
|
||||||
{ e = NULL;
|
{ e = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1704,7 +1724,12 @@ Expression *GotoStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s GotoStatement::interpret()\n", loc.toChars());
|
printf("%s GotoStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
assert(label && label->statement);
|
assert(label && label->statement);
|
||||||
istate->gotoTarget = label->statement;
|
istate->gotoTarget = label->statement;
|
||||||
return EXP_GOTO_INTERPRET;
|
return EXP_GOTO_INTERPRET;
|
||||||
@@ -1715,7 +1740,12 @@ Expression *GotoCaseStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s GotoCaseStatement::interpret()\n", loc.toChars());
|
printf("%s GotoCaseStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
assert(cs);
|
assert(cs);
|
||||||
istate->gotoTarget = cs;
|
istate->gotoTarget = cs;
|
||||||
return EXP_GOTO_INTERPRET;
|
return EXP_GOTO_INTERPRET;
|
||||||
@@ -1726,7 +1756,12 @@ Expression *GotoDefaultStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s GotoDefaultStatement::interpret()\n", loc.toChars());
|
printf("%s GotoDefaultStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
assert(sw && sw->sdefault);
|
assert(sw && sw->sdefault);
|
||||||
istate->gotoTarget = sw->sdefault;
|
istate->gotoTarget = sw->sdefault;
|
||||||
return EXP_GOTO_INTERPRET;
|
return EXP_GOTO_INTERPRET;
|
||||||
@@ -1748,7 +1783,22 @@ Expression *TryCatchStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s TryCatchStatement::interpret()\n", loc.toChars());
|
printf("%s TryCatchStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#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;
|
Expression *e = body ? body->interpret(istate) : NULL;
|
||||||
if (e == EXP_CANT_INTERPRET)
|
if (e == EXP_CANT_INTERPRET)
|
||||||
return e;
|
return e;
|
||||||
@@ -1760,21 +1810,36 @@ Expression *TryCatchStatement::interpret(InterState *istate)
|
|||||||
// Search for an appropriate catch clause.
|
// Search for an appropriate catch clause.
|
||||||
for (size_t i = 0; i < catches->dim; i++)
|
for (size_t i = 0; i < catches->dim; i++)
|
||||||
{
|
{
|
||||||
#if DMDV1
|
|
||||||
Catch *ca = (Catch *)catches->data[i];
|
|
||||||
#else
|
|
||||||
Catch *ca = (*catches)[i];
|
Catch *ca = (*catches)[i];
|
||||||
#endif
|
|
||||||
Type *catype = ca->type;
|
Type *catype = ca->type;
|
||||||
|
|
||||||
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
|
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
|
||||||
{ // Execute the handler
|
{
|
||||||
|
// Execute the handler
|
||||||
if (ca->var)
|
if (ca->var)
|
||||||
{
|
{
|
||||||
ctfeStack.push(ca->var);
|
ctfeStack.push(ca->var);
|
||||||
ca->var->setValue(ex->thrown);
|
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;
|
return e;
|
||||||
@@ -1820,7 +1885,18 @@ Expression *TryFinallyStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s TryFinallyStatement::interpret()\n", loc.toChars());
|
printf("%s TryFinallyStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#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;
|
Expression *e = body ? body->interpret(istate) : NULL;
|
||||||
if (e == EXP_CANT_INTERPRET)
|
if (e == EXP_CANT_INTERPRET)
|
||||||
return e;
|
return e;
|
||||||
@@ -1842,7 +1918,12 @@ Expression *ThrowStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s ThrowStatement::interpret()\n", loc.toChars());
|
printf("%s ThrowStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Expression *e = exp->interpret(istate);
|
Expression *e = exp->interpret(istate);
|
||||||
if (exceptionOrCantInterpret(e))
|
if (exceptionOrCantInterpret(e))
|
||||||
return e;
|
return e;
|
||||||
@@ -1866,7 +1947,12 @@ Expression *WithStatement::interpret(InterState *istate)
|
|||||||
if (exp->op == TOKimport || exp->op == TOKtype)
|
if (exp->op == TOKimport || exp->op == TOKtype)
|
||||||
return body ? body->interpret(istate) : EXP_VOID_INTERPRET;
|
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);
|
Expression *e = exp->interpret(istate);
|
||||||
if (exceptionOrCantInterpret(e))
|
if (exceptionOrCantInterpret(e))
|
||||||
return e;
|
return e;
|
||||||
@@ -1877,7 +1963,24 @@ Expression *WithStatement::interpret(InterState *istate)
|
|||||||
}
|
}
|
||||||
ctfeStack.push(wthis);
|
ctfeStack.push(wthis);
|
||||||
wthis->setValue(e);
|
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);
|
ctfeStack.pop(wthis);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -1887,7 +1990,12 @@ Expression *AsmStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("%s AsmStatement::interpret()\n", loc.toChars());
|
printf("%s AsmStatement::interpret()\n", loc.toChars());
|
||||||
#endif
|
#endif
|
||||||
START()
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
error("asm statements cannot be interpreted at compile time");
|
error("asm statements cannot be interpreted at compile time");
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
@@ -1898,7 +2006,12 @@ Expression *ImportStatement::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("ImportStatement::interpret()\n");
|
printf("ImportStatement::interpret()\n");
|
||||||
#endif
|
#endif
|
||||||
START();
|
if (istate->start)
|
||||||
|
{ if (istate->start != this)
|
||||||
|
return NULL;
|
||||||
|
istate->start = NULL;
|
||||||
|
}
|
||||||
|
;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2432,11 +2545,11 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
}
|
}
|
||||||
else if (s->isTupleDeclaration() && !v->init)
|
else if (s->isTupleDeclaration() && !v->init)
|
||||||
e = NULL;
|
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
|
e = NULL; // Just ignore static variables which aren't read or written yet
|
||||||
else
|
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;
|
e = EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2779,7 +2892,7 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is
|
|||||||
|| elemType->ty == Tdchar)
|
|| elemType->ty == Tdchar)
|
||||||
return createBlockDuplicatedStringLiteral(loc, newtype,
|
return createBlockDuplicatedStringLiteral(loc, newtype,
|
||||||
(unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
|
(unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
|
||||||
len, elemType->size());
|
len, (unsigned char)elemType->size());
|
||||||
return createBlockDuplicatedArrayLiteral(loc, newtype,
|
return createBlockDuplicatedArrayLiteral(loc, newtype,
|
||||||
elemType->defaultInitLiteral(loc),
|
elemType->defaultInitLiteral(loc),
|
||||||
len);
|
len);
|
||||||
@@ -3207,8 +3320,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
if (op == TOKconstruct && this->e1->op==TOKvar
|
if (op == TOKconstruct && this->e1->op==TOKvar
|
||||||
&& ((VarExp*)this->e1)->var->storage_class & STCref)
|
&& ((VarExp*)this->e1)->var->storage_class & STCref)
|
||||||
{
|
{
|
||||||
wantRef = true;
|
wantRef = true;
|
||||||
wantLvalueRef = true;
|
wantLvalueRef = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fp)
|
if (fp)
|
||||||
@@ -3353,8 +3466,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
returnValue = newval;
|
returnValue = newval;
|
||||||
if (e1->op == TOKarraylength)
|
if (e1->op == TOKarraylength)
|
||||||
{
|
{
|
||||||
size_t oldlen = oldval->toInteger();
|
size_t oldlen = (size_t)oldval->toInteger();
|
||||||
size_t newlen = newval->toInteger();
|
size_t newlen = (size_t)newval->toInteger();
|
||||||
if (oldlen == newlen) // no change required -- we're done!
|
if (oldlen == newlen) // no change required -- we're done!
|
||||||
return returnValue;
|
return returnValue;
|
||||||
// Now change the assignment from arr.length = n into arr = newval
|
// Now change the assignment from arr.length = n into arr = newval
|
||||||
@@ -3894,9 +4007,9 @@ bool interpretAssignToIndex(InterState *istate, Loc loc,
|
|||||||
if (existingAE)
|
if (existingAE)
|
||||||
{
|
{
|
||||||
if (newval->op == TOKstructliteral)
|
if (newval->op == TOKstructliteral)
|
||||||
assignInPlace((*existingAE->elements)[indexToModify], newval);
|
assignInPlace((*existingAE->elements)[(size_t)indexToModify], newval);
|
||||||
else
|
else
|
||||||
(*existingAE->elements)[indexToModify] = newval;
|
(*existingAE->elements)[(size_t)indexToModify] = newval;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (existingSE)
|
if (existingSE)
|
||||||
@@ -3907,12 +4020,12 @@ bool interpretAssignToIndex(InterState *istate, Loc loc,
|
|||||||
originalExp->error("cannot modify read-only string literal %s", ie->e1->toChars());
|
originalExp->error("cannot modify read-only string literal %s", ie->e1->toChars());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unsigned value = newval->toInteger();
|
dinteger_t value = newval->toInteger();
|
||||||
switch (existingSE->sz)
|
switch (existingSE->sz)
|
||||||
{
|
{
|
||||||
case 1: s[indexToModify] = value; break;
|
case 1: s[(size_t)indexToModify] = (utf8_t)value; break;
|
||||||
case 2: ((unsigned short *)s)[indexToModify] = value; break;
|
case 2: ((unsigned short *)s)[(size_t)indexToModify] = (unsigned short)value; break;
|
||||||
case 4: ((unsigned *)s)[indexToModify] = value; break;
|
case 4: ((unsigned *)s)[(size_t)indexToModify] = (unsigned)value; break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@@ -4008,9 +4121,9 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc,
|
|||||||
if (exceptionOrCantInterpret(lower))
|
if (exceptionOrCantInterpret(lower))
|
||||||
return lower;
|
return lower;
|
||||||
|
|
||||||
size_t dim = dollar;
|
unsigned dim = (unsigned)dollar;
|
||||||
size_t upperbound = upper ? upper->toInteger() : dim;
|
size_t upperbound = (size_t)(upper ? upper->toInteger() : dim);
|
||||||
int lowerbound = lower ? lower->toInteger() : 0;
|
int lowerbound = (int)(lower ? lower->toInteger() : 0);
|
||||||
|
|
||||||
if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim)))
|
if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim)))
|
||||||
{
|
{
|
||||||
@@ -4137,13 +4250,13 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc,
|
|||||||
Type *elemtype = existingAE->type->nextOf();
|
Type *elemtype = existingAE->type->nextOf();
|
||||||
for (size_t j = 0; j < newelems->dim; j++)
|
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;
|
return newval;
|
||||||
}
|
}
|
||||||
else if (newval->op == TOKstring && existingSE)
|
else if (newval->op == TOKstring && existingSE)
|
||||||
{
|
{
|
||||||
sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, firstIndex);
|
sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, (size_t)firstIndex);
|
||||||
return newval;
|
return newval;
|
||||||
}
|
}
|
||||||
else if (newval->op == TOKstring && existingAE
|
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.
|
{ /* Mixed slice: it was initialized as an array literal of chars.
|
||||||
* Now a slice of it is being set with a string.
|
* 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;
|
return newval;
|
||||||
}
|
}
|
||||||
else if (newval->op == TOKarrayliteral && existingSE)
|
else if (newval->op == TOKarrayliteral && existingSE)
|
||||||
{ /* Mixed slice: it was initialized as a string literal.
|
{ /* Mixed slice: it was initialized as a string literal.
|
||||||
* Now a slice of it is being set with an array 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;
|
return newval;
|
||||||
}
|
}
|
||||||
else if (existingSE)
|
else if (existingSE)
|
||||||
{ // String literal block slice assign
|
{ // String literal block slice assign
|
||||||
unsigned value = newval->toInteger();
|
dinteger_t value = newval->toInteger();
|
||||||
utf8_t *s = (utf8_t *)existingSE->string;
|
utf8_t *s = (utf8_t *)existingSE->string;
|
||||||
for (size_t j = 0; j < upperbound-lowerbound; j++)
|
for (size_t j = 0; j < upperbound-lowerbound; j++)
|
||||||
{
|
{
|
||||||
switch (existingSE->sz)
|
switch (existingSE->sz)
|
||||||
{
|
{
|
||||||
case 1: s[j+firstIndex] = value; break;
|
case 1: s[(size_t)(j+firstIndex)] = (utf8_t)value; break;
|
||||||
case 2: ((unsigned short *)s)[j+firstIndex] = value; break;
|
case 2: ((unsigned short *)s)[(size_t)(j+firstIndex)] = (unsigned short)value; break;
|
||||||
case 4: ((unsigned *)s)[j+firstIndex] = value; break;
|
case 4: ((unsigned *)s)[(size_t)(j+firstIndex)] = (unsigned)value; break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@@ -4208,13 +4321,13 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc,
|
|||||||
{
|
{
|
||||||
if (!directblk)
|
if (!directblk)
|
||||||
// Multidimensional array block assign
|
// Multidimensional array block assign
|
||||||
recursiveBlockAssign((ArrayLiteralExp *)(*w)[j+firstIndex], newval, wantRef);
|
recursiveBlockAssign((ArrayLiteralExp *)(*w)[(size_t)(j+firstIndex)], newval, wantRef);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (wantRef || cow)
|
if (wantRef || cow)
|
||||||
(*existingAE->elements)[j+firstIndex] = newval;
|
(*existingAE->elements)[(size_t)(j+firstIndex)] = newval;
|
||||||
else
|
else
|
||||||
assignInPlace((*existingAE->elements)[j+firstIndex], newval);
|
assignInPlace((*existingAE->elements)[(size_t)(j+firstIndex)], newval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (goal == ctfeNeedNothing)
|
if (goal == ctfeNeedNothing)
|
||||||
@@ -4376,7 +4489,7 @@ Expression *BinExp::interpretFourPointerRelation(InterState *istate, CtfeGoal go
|
|||||||
if ( !pointToSameMemoryBlock(agg1, agg2)
|
if ( !pointToSameMemoryBlock(agg1, agg2)
|
||||||
&& agg1->op != TOKnull && agg2->op != TOKnull)
|
&& agg1->op != TOKnull && agg2->op != TOKnull)
|
||||||
{ // Here it is either CANT_INTERPRET,
|
{ // Here it is either CANT_INTERPRET,
|
||||||
// or an IsInside comparison returning FALSE.
|
// or an IsInside comparison returning false.
|
||||||
p3 = p3->interpret(istate);
|
p3 = p3->interpret(istate);
|
||||||
if (p3 == EXP_CANT_INTERPRET)
|
if (p3 == EXP_CANT_INTERPRET)
|
||||||
return p3;
|
return p3;
|
||||||
@@ -4463,7 +4576,7 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
int result;
|
int result;
|
||||||
if (e != EXP_CANT_INTERPRET)
|
if (e != EXP_CANT_INTERPRET)
|
||||||
{
|
{
|
||||||
if (e->isBool(FALSE))
|
if (e->isBool(false))
|
||||||
result = 0;
|
result = 0;
|
||||||
else if (isTrueBool(e))
|
else if (isTrueBool(e))
|
||||||
{
|
{
|
||||||
@@ -4475,7 +4588,7 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
assert(type->ty == Tvoid);
|
assert(type->ty == Tvoid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (e->isBool(FALSE))
|
if (e->isBool(false))
|
||||||
result = 0;
|
result = 0;
|
||||||
else if (isTrueBool(e))
|
else if (isTrueBool(e))
|
||||||
result = 1;
|
result = 1;
|
||||||
@@ -4516,7 +4629,7 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
{
|
{
|
||||||
if (isTrueBool(e))
|
if (isTrueBool(e))
|
||||||
result = 1;
|
result = 1;
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
{
|
{
|
||||||
e = e2->interpret(istate);
|
e = e2->interpret(istate);
|
||||||
if (exceptionOrCantInterpret(e))
|
if (exceptionOrCantInterpret(e))
|
||||||
@@ -4529,7 +4642,7 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
}
|
}
|
||||||
if (e != EXP_CANT_INTERPRET)
|
if (e != EXP_CANT_INTERPRET)
|
||||||
{
|
{
|
||||||
if (e->isBool(FALSE))
|
if (e->isBool(false))
|
||||||
result = 0;
|
result = 0;
|
||||||
else if (isTrueBool(e))
|
else if (isTrueBool(e))
|
||||||
result = 1;
|
result = 1;
|
||||||
@@ -4788,14 +4901,18 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
}
|
}
|
||||||
eresult = fd->interpret(istate, arguments, pthis);
|
eresult = fd->interpret(istate, arguments, pthis);
|
||||||
if (eresult == EXP_CANT_INTERPRET)
|
if (eresult == EXP_CANT_INTERPRET)
|
||||||
{ // Print a stack trace.
|
{
|
||||||
|
// Print a stack trace.
|
||||||
if (!global.gag)
|
if (!global.gag)
|
||||||
showCtfeBackTrace(istate, this, fd);
|
showCtfeBackTrace(istate, this, fd);
|
||||||
}
|
}
|
||||||
else if (eresult == EXP_VOID_INTERPRET)
|
else if (eresult == EXP_VOID_INTERPRET)
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
eresult->type = type;
|
||||||
eresult->loc = loc;
|
eresult->loc = loc;
|
||||||
|
}
|
||||||
return eresult;
|
return eresult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4888,7 +5005,7 @@ Expression *CondExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
return e;
|
return e;
|
||||||
if (isTrueBool(e))
|
if (isTrueBool(e))
|
||||||
e = e1->interpret(istate, goal);
|
e = e1->interpret(istate, goal);
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
e = e2->interpret(istate, goal);
|
e = e2->interpret(istate, goal);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -5412,7 +5529,7 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
Expression *xx = NULL;
|
Expression *xx = NULL;
|
||||||
if (ie->e1->op == TOKarrayliteral && ie->e2->op == TOKint64)
|
if (ie->e1->op == TOKarrayliteral && ie->e2->op == TOKint64)
|
||||||
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)ie->e1;
|
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)ie->e1;
|
||||||
uinteger_t indx = ie->e2->toInteger();
|
size_t indx = (size_t)ie->e2->toInteger();
|
||||||
if (indx < ale->elements->dim)
|
if (indx < ale->elements->dim)
|
||||||
xx = (*ale->elements)[indx];
|
xx = (*ale->elements)[indx];
|
||||||
}
|
}
|
||||||
@@ -5528,7 +5645,7 @@ Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
if (isTrueBool(e1))
|
if (isTrueBool(e1))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (e1->isBool(FALSE))
|
else if (e1->isBool(false))
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
@@ -5583,7 +5700,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
if (ex->op == TOKstructliteral)
|
if (ex->op == TOKstructliteral)
|
||||||
{ StructLiteralExp *se = (StructLiteralExp *)ex;
|
{ StructLiteralExp *se = (StructLiteralExp *)ex;
|
||||||
dinteger_t offset = ae->e2->toInteger();
|
dinteger_t offset = ae->e2->toInteger();
|
||||||
e = se->getField(type, offset);
|
e = se->getField(type, (unsigned)offset);
|
||||||
if (!e)
|
if (!e)
|
||||||
e = EXP_CANT_INTERPRET;
|
e = EXP_CANT_INTERPRET;
|
||||||
return e;
|
return e;
|
||||||
@@ -5591,16 +5708,17 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
}
|
}
|
||||||
e = Ptr(type, e1);
|
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
|
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).
|
// 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()))
|
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);
|
e = paintTypeOntoLiteral(type, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ldone:
|
||||||
#if LOG
|
#if LOG
|
||||||
if (e == EXP_CANT_INTERPRET)
|
if (e == EXP_CANT_INTERPRET)
|
||||||
printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
|
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 *charType = (*fd->parameters)[numParams-1]->type;
|
||||||
Type *indexType = numParams == 2 ? (*fd->parameters)[0]->type
|
Type *indexType = numParams == 2 ? (*fd->parameters)[0]->type
|
||||||
: Type::tsize_t;
|
: Type::tsize_t;
|
||||||
uinteger_t len = resolveArrayLength(str);
|
size_t len = (size_t)resolveArrayLength(str);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return new IntegerExp(deleg->loc, 0, indexType);
|
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
|
{ // If it is an array literal, copy the code points into the buffer
|
||||||
size_t buflen = 1; // #code points in the buffer
|
size_t buflen = 1; // #code points in the buffer
|
||||||
size_t n = 1; // #code points in this char
|
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)
|
switch(sz)
|
||||||
{
|
{
|
||||||
@@ -6148,7 +6267,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
|
|||||||
|
|
||||||
Expression * r = (*ale->elements)[indx];
|
Expression * r = (*ale->elements)[indx];
|
||||||
assert(r->op == TOKint64);
|
assert(r->op == TOKint64);
|
||||||
rawvalue = ((IntegerExp *)r)->value;
|
rawvalue = (dchar_t)((IntegerExp *)r)->value;
|
||||||
n = 1;
|
n = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -6303,7 +6422,10 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
|
|||||||
}
|
}
|
||||||
e = eval_builtin(loc, b, &args);
|
e = eval_builtin(loc, b, &args);
|
||||||
if (!e)
|
if (!e)
|
||||||
|
{
|
||||||
|
error(loc, "cannot evaluate unimplemented builtin %s at compile time", fd->toChars());
|
||||||
e = EXP_CANT_INTERPRET;
|
e = EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -807,9 +807,7 @@ void ConditionalDeclaration::toJson(JsonOut *json)
|
|||||||
|
|
||||||
void ClassInfoDeclaration::toJson(JsonOut *json) { }
|
void ClassInfoDeclaration::toJson(JsonOut *json) { }
|
||||||
void TypeInfoDeclaration::toJson(JsonOut *json) { }
|
void TypeInfoDeclaration::toJson(JsonOut *json) { }
|
||||||
#if DMDV2
|
|
||||||
void PostBlitDeclaration::toJson(JsonOut *json) { }
|
void PostBlitDeclaration::toJson(JsonOut *json) { }
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void Declaration::toJson(JsonOut *json)
|
void Declaration::toJson(JsonOut *json)
|
||||||
@@ -966,14 +964,10 @@ void TemplateDeclaration::toJson(JsonOut *json)
|
|||||||
TemplateTypeParameter *type = s->isTemplateTypeParameter();
|
TemplateTypeParameter *type = s->isTemplateTypeParameter();
|
||||||
if (type)
|
if (type)
|
||||||
{
|
{
|
||||||
#if DMDV2
|
|
||||||
if (s->isTemplateThisParameter())
|
if (s->isTemplateThisParameter())
|
||||||
json->property("kind", "this");
|
json->property("kind", "this");
|
||||||
else
|
else
|
||||||
json->property("kind", "type");
|
json->property("kind", "type");
|
||||||
#else
|
|
||||||
json->property("kind", "type");
|
|
||||||
#endif
|
|
||||||
json->property("type", "deco", type->specType);
|
json->property("type", "deco", type->specType);
|
||||||
|
|
||||||
json->property("default", "defaultDeco", type->defaultType);
|
json->property("default", "defaultDeco", type->defaultType);
|
||||||
|
|||||||
+165
-237
@@ -36,7 +36,7 @@
|
|||||||
#include "id.h"
|
#include "id.h"
|
||||||
#include "module.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 LS 0x2028 // UTF line separator
|
||||||
#define PS 0x2029 // UTF paragraph separator
|
#define PS 0x2029 // UTF paragraph separator
|
||||||
@@ -53,9 +53,9 @@ const int CMoctal = 0x1;
|
|||||||
const int CMhex = 0x2;
|
const int CMhex = 0x2;
|
||||||
const int CMidchar = 0x4;
|
const int CMidchar = 0x4;
|
||||||
|
|
||||||
inline bool isoctal (utf8_t c) { return cmtable[c] & CMoctal; }
|
inline bool isoctal (utf8_t c) { return (cmtable[c] & CMoctal) != 0; }
|
||||||
inline bool ishex (utf8_t c) { return cmtable[c] & CMhex; }
|
inline bool ishex (utf8_t c) { return (cmtable[c] & CMhex) != 0; }
|
||||||
inline bool isidchar(utf8_t c) { return cmtable[c] & CMidchar; }
|
inline bool isidchar(utf8_t c) { return (cmtable[c] & CMidchar) != 0; }
|
||||||
|
|
||||||
static void cmtable_init()
|
static void cmtable_init()
|
||||||
{
|
{
|
||||||
@@ -99,55 +99,55 @@ const char *Token::toChars()
|
|||||||
{ const char *p;
|
{ const char *p;
|
||||||
static char buffer[3 + 3 * sizeof(float80value) + 1];
|
static char buffer[3 + 3 * sizeof(float80value) + 1];
|
||||||
|
|
||||||
p = buffer;
|
p = &buffer[0];
|
||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case TOKint32v:
|
case TOKint32v:
|
||||||
sprintf(buffer,"%d",int32value);
|
sprintf(&buffer[0],"%d",int32value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKuns32v:
|
case TOKuns32v:
|
||||||
case TOKcharv:
|
case TOKcharv:
|
||||||
case TOKwcharv:
|
case TOKwcharv:
|
||||||
case TOKdcharv:
|
case TOKdcharv:
|
||||||
sprintf(buffer,"%uU",uns32value);
|
sprintf(&buffer[0],"%uU",uns32value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKint64v:
|
case TOKint64v:
|
||||||
sprintf(buffer,"%lldL",(longlong)int64value);
|
sprintf(&buffer[0],"%lldL",(longlong)int64value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKuns64v:
|
case TOKuns64v:
|
||||||
sprintf(buffer,"%lluUL",(ulonglong)uns64value);
|
sprintf(&buffer[0],"%lluUL",(ulonglong)uns64value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKfloat32v:
|
case TOKfloat32v:
|
||||||
ld_sprint(buffer, 'g', float80value);
|
ld_sprint(&buffer[0], 'g', float80value);
|
||||||
strcat(buffer, "f");
|
strcat(&buffer[0], "f");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKfloat64v:
|
case TOKfloat64v:
|
||||||
ld_sprint(buffer, 'g', float80value);
|
ld_sprint(&buffer[0], 'g', float80value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKfloat80v:
|
case TOKfloat80v:
|
||||||
ld_sprint(buffer, 'g', float80value);
|
ld_sprint(&buffer[0], 'g', float80value);
|
||||||
strcat(buffer, "L");
|
strcat(&buffer[0], "L");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKimaginary32v:
|
case TOKimaginary32v:
|
||||||
ld_sprint(buffer, 'g', float80value);
|
ld_sprint(&buffer[0], 'g', float80value);
|
||||||
strcat(buffer, "fi");
|
strcat(&buffer[0], "fi");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKimaginary64v:
|
case TOKimaginary64v:
|
||||||
ld_sprint(buffer, 'g', float80value);
|
ld_sprint(&buffer[0], 'g', float80value);
|
||||||
strcat(buffer, "i");
|
strcat(&buffer[0], "i");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKimaginary80v:
|
case TOKimaginary80v:
|
||||||
ld_sprint(buffer, 'g', float80value);
|
ld_sprint(&buffer[0], 'g', float80value);
|
||||||
strcat(buffer, "Li");
|
strcat(&buffer[0], "Li");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKstring:
|
case TOKstring:
|
||||||
@@ -208,8 +208,8 @@ const char *Token::toChars(TOK value)
|
|||||||
|
|
||||||
p = tochars[value];
|
p = tochars[value];
|
||||||
if (!p)
|
if (!p)
|
||||||
{ sprintf(buffer,"TOK%d",value);
|
{ sprintf(&buffer[0],"TOK%d",value);
|
||||||
p = buffer;
|
p = &buffer[0];
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ StringTable Lexer::stringtable;
|
|||||||
OutBuffer Lexer::stringbuffer;
|
OutBuffer Lexer::stringbuffer;
|
||||||
|
|
||||||
Lexer::Lexer(Module *mod,
|
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)
|
int doDocComment, int commentToken)
|
||||||
{
|
{
|
||||||
scanloc = Loc(mod, 1);
|
scanloc = Loc(mod, 1);
|
||||||
@@ -409,7 +409,7 @@ Token *Lexer::peekPastParen(Token *tk)
|
|||||||
* 0 invalid
|
* 0 invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Lexer::isValidIdentifier(char *p)
|
int Lexer::isValidIdentifier(const char *p)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
@@ -503,7 +503,6 @@ void Lexer::scan(Token *t)
|
|||||||
t->value = hexStringConstant(t);
|
t->value = hexStringConstant(t);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
case 'q':
|
case 'q':
|
||||||
if (p[1] == '"')
|
if (p[1] == '"')
|
||||||
{
|
{
|
||||||
@@ -519,16 +518,14 @@ void Lexer::scan(Token *t)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto case_ident;
|
goto case_ident;
|
||||||
#endif
|
|
||||||
|
|
||||||
case '"':
|
case '"':
|
||||||
t->value = escapeStringConstant(t,0);
|
t->value = escapeStringConstant(t,0);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if ! TEXTUAL_ASSEMBLY_OUT
|
|
||||||
case '\\': // escaped string literal
|
case '\\': // escaped string literal
|
||||||
{ unsigned c;
|
{ unsigned c;
|
||||||
utf8_t *pstart = p;
|
const utf8_t *pstart = p;
|
||||||
|
|
||||||
stringbuffer.reset();
|
stringbuffer.reset();
|
||||||
do
|
do
|
||||||
@@ -555,21 +552,14 @@ void Lexer::scan(Token *t)
|
|||||||
memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
|
memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
|
||||||
t->postfix = 0;
|
t->postfix = 0;
|
||||||
t->value = TOKstring;
|
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);
|
error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart);
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||||
#if DMDV2
|
|
||||||
case 'p': /*case 'q': case 'r':*/ case 's': case 't':
|
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 'u': case 'v': case 'w': /*case 'x':*/ case 'y':
|
||||||
case 'z':
|
case 'z':
|
||||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||||
@@ -588,7 +578,7 @@ void Lexer::scan(Token *t)
|
|||||||
if (isidchar(c))
|
if (isidchar(c))
|
||||||
continue;
|
continue;
|
||||||
else if (c & 0x80)
|
else if (c & 0x80)
|
||||||
{ utf8_t *s = p;
|
{ const utf8_t *s = p;
|
||||||
unsigned u = decodeUTF();
|
unsigned u = decodeUTF();
|
||||||
if (isUniAlpha(u))
|
if (isUniAlpha(u))
|
||||||
continue;
|
continue;
|
||||||
@@ -617,28 +607,15 @@ void Lexer::scan(Token *t)
|
|||||||
if (!initdone) // lazy evaluation
|
if (!initdone) // lazy evaluation
|
||||||
{
|
{
|
||||||
initdone = true;
|
initdone = true;
|
||||||
time_t t;
|
time_t ct;
|
||||||
::time(&t);
|
::time(&ct);
|
||||||
char *p = ctime(&t);
|
char *p = ctime(&ct);
|
||||||
assert(p);
|
assert(p);
|
||||||
sprintf(date, "%.6s %.4s", p + 4, p + 20);
|
sprintf(&date[0], "%.6s %.4s", p + 4, p + 20);
|
||||||
sprintf(time, "%.8s", p + 11);
|
sprintf(&time[0], "%.8s", p + 11);
|
||||||
sprintf(timestamp, "%.24s", p);
|
sprintf(×tamp[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)
|
if (id == Id::DATE)
|
||||||
{
|
{
|
||||||
t->ustring = (utf8_t *)date;
|
t->ustring = (utf8_t *)date;
|
||||||
@@ -669,7 +646,7 @@ void Lexer::scan(Token *t)
|
|||||||
|
|
||||||
for (const char *p = global.version + 1; 1; p++)
|
for (const char *p = global.version + 1; 1; p++)
|
||||||
{
|
{
|
||||||
char c = *p;
|
c = *p;
|
||||||
if (isdigit((utf8_t)c))
|
if (isdigit((utf8_t)c))
|
||||||
minor = minor * 10 + c - '0';
|
minor = minor * 10 + c - '0';
|
||||||
else if (c == '.')
|
else if (c == '.')
|
||||||
@@ -686,7 +663,6 @@ void Lexer::scan(Token *t)
|
|||||||
t->value = TOKint64v;
|
t->value = TOKint64v;
|
||||||
t->uns64value = major * 1000 + minor;
|
t->uns64value = major * 1000 + minor;
|
||||||
}
|
}
|
||||||
#if DMDV2
|
|
||||||
else if (id == Id::EOFX)
|
else if (id == Id::EOFX)
|
||||||
{
|
{
|
||||||
t->value = TOKeof;
|
t->value = TOKeof;
|
||||||
@@ -694,7 +670,6 @@ void Lexer::scan(Token *t)
|
|||||||
while (!(*p == 0 || *p == 0x1A))
|
while (!(*p == 0 || *p == 0x1A))
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
//printf("t->value = %d\n",t->value);
|
//printf("t->value = %d\n",t->value);
|
||||||
return;
|
return;
|
||||||
@@ -962,12 +937,6 @@ void Lexer::scan(Token *t)
|
|||||||
{ p++;
|
{ p++;
|
||||||
t->value = TOKminass;
|
t->value = TOKminass;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
else if (*p == '>')
|
|
||||||
{ p++;
|
|
||||||
t->value = TOKarrow;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (*p == '-')
|
else if (*p == '-')
|
||||||
{ p++;
|
{ p++;
|
||||||
t->value = TOKminusminus;
|
t->value = TOKminusminus;
|
||||||
@@ -1089,12 +1058,10 @@ void Lexer::scan(Token *t)
|
|||||||
{ p++;
|
{ p++;
|
||||||
t->value = TOKequal; // ==
|
t->value = TOKequal; // ==
|
||||||
}
|
}
|
||||||
#if DMDV2
|
|
||||||
else if (*p == '>')
|
else if (*p == '>')
|
||||||
{ p++;
|
{ p++;
|
||||||
t->value = TOKgoesto; // =>
|
t->value = TOKgoesto; // =>
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
t->value = TOKassign; // =
|
t->value = TOKassign; // =
|
||||||
return;
|
return;
|
||||||
@@ -1109,7 +1076,6 @@ void Lexer::scan(Token *t)
|
|||||||
t->value = TOKtilde; // ~
|
t->value = TOKtilde; // ~
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
case '^':
|
case '^':
|
||||||
p++;
|
p++;
|
||||||
if (*p == '^')
|
if (*p == '^')
|
||||||
@@ -1128,7 +1094,6 @@ void Lexer::scan(Token *t)
|
|||||||
else
|
else
|
||||||
t->value = TOKxor; // ^
|
t->value = TOKxor; // ^
|
||||||
return;
|
return;
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SINGLE(c,tok) case c: p++; t->value = tok; return;
|
#define SINGLE(c,tok) case c: p++; t->value = tok; return;
|
||||||
|
|
||||||
@@ -1143,9 +1108,7 @@ void Lexer::scan(Token *t)
|
|||||||
SINGLE(';', TOKsemicolon)
|
SINGLE(';', TOKsemicolon)
|
||||||
SINGLE(':', TOKcolon)
|
SINGLE(':', TOKcolon)
|
||||||
SINGLE('$', TOKdollar)
|
SINGLE('$', TOKdollar)
|
||||||
#if DMDV2
|
|
||||||
SINGLE('@', TOKat)
|
SINGLE('@', TOKat)
|
||||||
#endif
|
|
||||||
#undef SINGLE
|
#undef SINGLE
|
||||||
|
|
||||||
#define DOUBLE(c1,tok1,c2,tok2) \
|
#define DOUBLE(c1,tok1,c2,tok2) \
|
||||||
@@ -1161,9 +1124,6 @@ void Lexer::scan(Token *t)
|
|||||||
|
|
||||||
DOUBLE('*', TOKmul, '=', TOKmulass)
|
DOUBLE('*', TOKmul, '=', TOKmulass)
|
||||||
DOUBLE('%', TOKmod, '=', TOKmodass)
|
DOUBLE('%', TOKmod, '=', TOKmodass)
|
||||||
#if DMDV1
|
|
||||||
DOUBLE('^', TOKxor, '=', TOKxorass)
|
|
||||||
#endif
|
|
||||||
#undef DOUBLE
|
#undef DOUBLE
|
||||||
|
|
||||||
case '#':
|
case '#':
|
||||||
@@ -1218,9 +1178,6 @@ void Lexer::scan(Token *t)
|
|||||||
unsigned Lexer::escapeSequence()
|
unsigned Lexer::escapeSequence()
|
||||||
{ unsigned c = *p;
|
{ unsigned c = *p;
|
||||||
|
|
||||||
#ifdef TEXTUAL_ASSEMBLY_OUT
|
|
||||||
return c;
|
|
||||||
#endif
|
|
||||||
int n;
|
int n;
|
||||||
int ndigits;
|
int ndigits;
|
||||||
|
|
||||||
@@ -1253,14 +1210,14 @@ unsigned Lexer::escapeSequence()
|
|||||||
Lhex:
|
Lhex:
|
||||||
p++;
|
p++;
|
||||||
c = *p;
|
c = *p;
|
||||||
if (ishex(c))
|
if (ishex((utf8_t)c))
|
||||||
{ unsigned v;
|
{ unsigned v;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
v = 0;
|
v = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (isdigit(c))
|
if (isdigit((utf8_t)c))
|
||||||
c -= '0';
|
c -= '0';
|
||||||
else if (islower(c))
|
else if (islower(c))
|
||||||
c -= 'a' - 10;
|
c -= 'a' - 10;
|
||||||
@@ -1270,7 +1227,7 @@ unsigned Lexer::escapeSequence()
|
|||||||
c = *++p;
|
c = *++p;
|
||||||
if (++n == ndigits)
|
if (++n == ndigits)
|
||||||
break;
|
break;
|
||||||
if (!ishex(c))
|
if (!ishex((utf8_t)c))
|
||||||
{ error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
|
{ error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1286,7 +1243,7 @@ unsigned Lexer::escapeSequence()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '&': // named character entity
|
case '&': // named character entity
|
||||||
for (utf8_t *idstart = ++p; 1; p++)
|
for (const utf8_t *idstart = ++p; 1; p++)
|
||||||
{
|
{
|
||||||
switch (*p)
|
switch (*p)
|
||||||
{
|
{
|
||||||
@@ -1316,7 +1273,7 @@ unsigned Lexer::escapeSequence()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (isoctal(c))
|
if (isoctal((utf8_t)c))
|
||||||
{ unsigned v;
|
{ unsigned v;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
@@ -1325,7 +1282,7 @@ unsigned Lexer::escapeSequence()
|
|||||||
{
|
{
|
||||||
v = v * 8 + (c - '0');
|
v = v * 8 + (c - '0');
|
||||||
c = *++p;
|
c = *++p;
|
||||||
} while (++n < 3 && isoctal(c));
|
} while (++n < 3 && isoctal((utf8_t)c));
|
||||||
c = v;
|
c = v;
|
||||||
if (c > 0xFF)
|
if (c > 0xFF)
|
||||||
error("0%03o is larger than a byte", c);
|
error("0%03o is larger than a byte", c);
|
||||||
@@ -1484,7 +1441,6 @@ TOK Lexer::hexStringConstant(Token *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
/**************************************
|
/**************************************
|
||||||
* Lex delimited strings:
|
* Lex delimited strings:
|
||||||
* q"(foo(xxx))" // "foo(xxx)"
|
* q"(foo(xxx))" // "foo(xxx)"
|
||||||
@@ -1566,15 +1522,15 @@ TOK Lexer::delimitedStringConstant(Token *t)
|
|||||||
delimright = '>';
|
delimright = '>';
|
||||||
else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
|
else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
|
||||||
{ // Start of identifier; must be a heredoc
|
{ // Start of identifier; must be a heredoc
|
||||||
Token t;
|
Token tok;
|
||||||
p--;
|
p--;
|
||||||
scan(&t); // read in heredoc identifier
|
scan(&tok); // read in heredoc identifier
|
||||||
if (t.value != TOKidentifier)
|
if (tok.value != TOKidentifier)
|
||||||
{ error("identifier expected for heredoc, not %s", t.toChars());
|
{ error("identifier expected for heredoc, not %s", tok.toChars());
|
||||||
delimright = c;
|
delimright = c;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ hereid = t.ident;
|
{ hereid = tok.ident;
|
||||||
//printf("hereid = '%s'\n", hereid->toChars());
|
//printf("hereid = '%s'\n", hereid->toChars());
|
||||||
blankrol = 1;
|
blankrol = 1;
|
||||||
}
|
}
|
||||||
@@ -1583,10 +1539,8 @@ TOK Lexer::delimitedStringConstant(Token *t)
|
|||||||
else
|
else
|
||||||
{ delimright = c;
|
{ delimright = c;
|
||||||
nest = 0;
|
nest = 0;
|
||||||
#if DMDV2
|
|
||||||
if (isspace(c))
|
if (isspace(c))
|
||||||
error("delimiter cannot be whitespace");
|
error("delimiter cannot be whitespace");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1608,17 +1562,13 @@ TOK Lexer::delimitedStringConstant(Token *t)
|
|||||||
}
|
}
|
||||||
else if (c == delimright)
|
else if (c == delimright)
|
||||||
goto Ldone;
|
goto Ldone;
|
||||||
if (startline && isalpha(c)
|
if (startline && isalpha(c) && hereid)
|
||||||
#if DMDV2
|
{ Token tok;
|
||||||
&& hereid
|
const utf8_t *psave = p;
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{ Token t;
|
|
||||||
utf8_t *psave = p;
|
|
||||||
p--;
|
p--;
|
||||||
scan(&t); // read in possible heredoc identifier
|
scan(&tok); // read in possible heredoc identifier
|
||||||
//printf("endid = '%s'\n", t.ident->toChars());
|
//printf("endid = '%s'\n", tok.ident->toChars());
|
||||||
if (t.value == TOKidentifier && t.ident->equals(hereid))
|
if (tok.value == TOKidentifier && tok.ident->equals(hereid))
|
||||||
{ /* should check that rest of line is blank
|
{ /* should check that rest of line is blank
|
||||||
*/
|
*/
|
||||||
goto Ldone;
|
goto Ldone;
|
||||||
@@ -1633,6 +1583,8 @@ TOK Lexer::delimitedStringConstant(Token *t)
|
|||||||
Ldone:
|
Ldone:
|
||||||
if (*p == '"')
|
if (*p == '"')
|
||||||
p++;
|
p++;
|
||||||
|
else if (hereid)
|
||||||
|
error("delimited string must end in %s\"", hereid->toChars());
|
||||||
else
|
else
|
||||||
error("delimited string must end in %c\"", delimright);
|
error("delimited string must end in %c\"", delimright);
|
||||||
t->len = stringbuffer.offset;
|
t->len = stringbuffer.offset;
|
||||||
@@ -1663,7 +1615,7 @@ TOK Lexer::tokenStringConstant(Token *t)
|
|||||||
{
|
{
|
||||||
unsigned nest = 1;
|
unsigned nest = 1;
|
||||||
Loc start = scanloc;
|
Loc start = scanloc;
|
||||||
utf8_t *pstart = ++p;
|
const utf8_t *pstart = ++p;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{ Token tok;
|
{ Token tok;
|
||||||
@@ -1704,7 +1656,6 @@ Lerror:
|
|||||||
return TOKstring;
|
return TOKstring;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
@@ -1722,7 +1673,6 @@ TOK Lexer::escapeStringConstant(Token *t, int wide)
|
|||||||
c = *p++;
|
c = *p++;
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
#if !( TEXTUAL_ASSEMBLY_OUT )
|
|
||||||
case '\\':
|
case '\\':
|
||||||
switch (*p)
|
switch (*p)
|
||||||
{
|
{
|
||||||
@@ -1738,7 +1688,6 @@ TOK Lexer::escapeStringConstant(Token *t, int wide)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case '\n':
|
case '\n':
|
||||||
scanloc.linnum++;
|
scanloc.linnum++;
|
||||||
break;
|
break;
|
||||||
@@ -1799,7 +1748,6 @@ TOK Lexer::charConstant(Token *t, int wide)
|
|||||||
c = *p++;
|
c = *p++;
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
#if ! TEXTUAL_ASSEMBLY_OUT
|
|
||||||
case '\\':
|
case '\\':
|
||||||
switch (*p)
|
switch (*p)
|
||||||
{
|
{
|
||||||
@@ -1819,7 +1767,6 @@ TOK Lexer::charConstant(Token *t, int wide)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case '\n':
|
case '\n':
|
||||||
L1:
|
L1:
|
||||||
scanloc.linnum++;
|
scanloc.linnum++;
|
||||||
@@ -1905,7 +1852,7 @@ TOK Lexer::number(Token *t)
|
|||||||
FLAGS flags = FLAGS_decimal;
|
FLAGS flags = FLAGS_decimal;
|
||||||
|
|
||||||
unsigned c;
|
unsigned c;
|
||||||
utf8_t *start;
|
const utf8_t *start;
|
||||||
TOK result;
|
TOK result;
|
||||||
|
|
||||||
//printf("Lexer::number()\n");
|
//printf("Lexer::number()\n");
|
||||||
@@ -1936,10 +1883,8 @@ TOK Lexer::number(Token *t)
|
|||||||
case '.':
|
case '.':
|
||||||
if (p[1] == '.') // .. is a separate token
|
if (p[1] == '.') // .. is a separate token
|
||||||
goto done;
|
goto done;
|
||||||
#if DMDV2
|
|
||||||
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
|
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
|
||||||
goto done;
|
goto done;
|
||||||
#endif
|
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
@@ -1978,10 +1923,8 @@ TOK Lexer::number(Token *t)
|
|||||||
}
|
}
|
||||||
if (c == '.' && p[1] != '.')
|
if (c == '.' && p[1] != '.')
|
||||||
{
|
{
|
||||||
#if DMDV2
|
|
||||||
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
|
if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80))
|
||||||
goto done;
|
goto done;
|
||||||
#endif
|
|
||||||
goto real;
|
goto real;
|
||||||
}
|
}
|
||||||
else if (c == 'i' || c == 'f' || c == 'F' ||
|
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_hex0: // reading hex number
|
||||||
case STATE_hex:
|
case STATE_hex:
|
||||||
if (!ishex(c))
|
if (!ishex((utf8_t)c))
|
||||||
{
|
{
|
||||||
if (c == '_') // ignore embedded _
|
if (c == '_') // ignore embedded _
|
||||||
{ p++;
|
{ p++;
|
||||||
@@ -2018,7 +1961,7 @@ TOK Lexer::number(Token *t)
|
|||||||
|
|
||||||
case STATE_octal: // reading octal number
|
case STATE_octal: // reading octal number
|
||||||
case STATE_octale: // reading octal number with non-octal digits
|
case STATE_octale: // reading octal number with non-octal digits
|
||||||
if (!isoctal(c))
|
if (!isoctal((utf8_t)c))
|
||||||
{
|
{
|
||||||
if (c == '_') // ignore embedded _
|
if (c == '_') // ignore embedded _
|
||||||
{ p++;
|
{ p++;
|
||||||
@@ -2078,14 +2021,10 @@ done:
|
|||||||
n = stringbuffer.data[0] - '0';
|
n = stringbuffer.data[0] - '0';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Convert string to integer
|
/* Convert string to integer
|
||||||
#if __DMC__
|
* Not everybody implements strtoull()
|
||||||
errno = 0;
|
* and besides, we don't want to deal with errno.
|
||||||
n = strtoull((char *)stringbuffer.data,NULL,0);
|
*/
|
||||||
if (errno == ERANGE)
|
|
||||||
error("integer overflow");
|
|
||||||
#else
|
|
||||||
// Not everybody implements strtoull()
|
|
||||||
char *p = (char *)stringbuffer.data;
|
char *p = (char *)stringbuffer.data;
|
||||||
int r = 10, d;
|
int r = 10, d;
|
||||||
|
|
||||||
@@ -2123,7 +2062,7 @@ done:
|
|||||||
n = n2 + d;
|
n = n2 + d;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (sizeof(n) > 8 &&
|
if (sizeof(n) > 8 &&
|
||||||
n > 0xFFFFFFFFFFFFFFFFULL) // if n needs more than 64 bits
|
n > 0xFFFFFFFFFFFFFFFFULL) // if n needs more than 64 bits
|
||||||
error("integer overflow");
|
error("integer overflow");
|
||||||
@@ -2154,11 +2093,9 @@ done:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (state == STATE_octal && n >= 8)
|
if (state == STATE_octal && n >= 8)
|
||||||
deprecation("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead",
|
deprecation("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead",
|
||||||
n, p - psuffix, psuffix, n, p - psuffix, psuffix);
|
n, p - psuffix, psuffix, n, p - psuffix, psuffix);
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (flags)
|
switch (flags)
|
||||||
{
|
{
|
||||||
@@ -2238,113 +2175,93 @@ done:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TOK Lexer::inreal(Token *t)
|
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");
|
//printf("Lexer::inreal()\n");
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(*p == '.' || isdigit(*p));
|
||||||
|
#endif
|
||||||
stringbuffer.reset();
|
stringbuffer.reset();
|
||||||
dblstate = 0;
|
const unsigned char *pstart = p;
|
||||||
hex = 0;
|
char hex = 0;
|
||||||
Lnext:
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
// Get next char from input
|
if (c == '.')
|
||||||
c = *p++;
|
|
||||||
//printf("dblstate = %d, c = '%c'\n", dblstate, c);
|
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
switch (dblstate)
|
c = *p++;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
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);
|
stringbuffer.writeByte(0);
|
||||||
|
|
||||||
|
TOK result;
|
||||||
t->float80value = Port::strtold((char *)stringbuffer.data, NULL);
|
t->float80value = Port::strtold((char *)stringbuffer.data, NULL);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
switch (*p)
|
switch (*p)
|
||||||
@@ -2395,6 +2312,21 @@ done:
|
|||||||
}
|
}
|
||||||
if (errno == ERANGE)
|
if (errno == ERANGE)
|
||||||
error("number is not representable");
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2413,7 +2345,7 @@ void Lexer::poundLine()
|
|||||||
|
|
||||||
scan(&tok);
|
scan(&tok);
|
||||||
if (tok.value == TOKint32v || tok.value == TOKint64v)
|
if (tok.value == TOKint32v || tok.value == TOKint64v)
|
||||||
{ linnum = tok.uns64value - 1;
|
{ linnum = (int)(tok.uns64value - 1);
|
||||||
if (linnum != tok.uns64value - 1)
|
if (linnum != tok.uns64value - 1)
|
||||||
error("line number out of range");
|
error("line number out of range");
|
||||||
}
|
}
|
||||||
@@ -2523,7 +2455,7 @@ unsigned Lexer::decodeUTF()
|
|||||||
{
|
{
|
||||||
dchar_t u;
|
dchar_t u;
|
||||||
utf8_t c;
|
utf8_t c;
|
||||||
utf8_t *s = p;
|
const utf8_t *s = p;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
@@ -2563,9 +2495,9 @@ void Lexer::getDocComment(Token *t, unsigned lineComment)
|
|||||||
|
|
||||||
/* Start of comment text skips over / * *, / + +, or / / /
|
/* 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 == '+')
|
if (ct == '*' || ct == '+')
|
||||||
qend -= 2;
|
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
|
// It's a line comment if the start of the doc comment comes
|
||||||
// after other non-whitespace on the same line.
|
// after other non-whitespace on the same line.
|
||||||
utf8_t** dc = (lineComment && anyToken)
|
const utf8_t** dc = (lineComment && anyToken)
|
||||||
? &t->lineComment
|
? &t->lineComment
|
||||||
: &t->blockComment;
|
: &t->blockComment;
|
||||||
|
|
||||||
@@ -2674,11 +2606,11 @@ void Lexer::getDocComment(Token *t, unsigned lineComment)
|
|||||||
* separated by a newline.
|
* 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);
|
//printf("Lexer::combineComments('%s', '%s')\n", c1, c2);
|
||||||
|
|
||||||
utf8_t *c = c2;
|
const utf8_t *c = c2;
|
||||||
|
|
||||||
if (c1)
|
if (c1)
|
||||||
{ c = 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 len1 = strlen((char *)c1);
|
||||||
size_t len2 = strlen((char *)c2);
|
size_t len2 = strlen((char *)c2);
|
||||||
|
|
||||||
c = (utf8_t *)mem.malloc(len1 + 1 + len2 + 1);
|
utf8_t *p = (utf8_t *)mem.malloc(len1 + 1 + len2 + 1);
|
||||||
memcpy(c, c1, len1);
|
memcpy(p, c1, len1);
|
||||||
if (len1 && c1[len1 - 1] != '\n')
|
if (len1 && c1[len1 - 1] != '\n')
|
||||||
{ c[len1] = '\n';
|
{ p[len1] = '\n';
|
||||||
len1++;
|
len1++;
|
||||||
}
|
}
|
||||||
memcpy(c + len1, c2, len2);
|
memcpy(p + len1, c2, len2);
|
||||||
c[len1 + len2] = 0;
|
p[len1 + len2] = 0;
|
||||||
|
c = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
@@ -2860,7 +2793,7 @@ static Keyword keywords[] =
|
|||||||
{ "__parameters", TOKparameters },
|
{ "__parameters", TOKparameters },
|
||||||
{ "ref", TOKref },
|
{ "ref", TOKref },
|
||||||
{ "macro", TOKmacro },
|
{ "macro", TOKmacro },
|
||||||
#if DMDV2
|
|
||||||
{ "pure", TOKpure },
|
{ "pure", TOKpure },
|
||||||
{ "nothrow", TOKnothrow },
|
{ "nothrow", TOKnothrow },
|
||||||
{ "__gshared", TOKgshared },
|
{ "__gshared", TOKgshared },
|
||||||
@@ -2874,7 +2807,6 @@ static Keyword keywords[] =
|
|||||||
{ "__PRETTY_FUNCTION__", TOKprettyfunc },
|
{ "__PRETTY_FUNCTION__", TOKprettyfunc },
|
||||||
{ "shared", TOKshared },
|
{ "shared", TOKshared },
|
||||||
{ "immutable", TOKimmutable },
|
{ "immutable", TOKimmutable },
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int Token::isKeyword()
|
int Token::isKeyword()
|
||||||
@@ -2922,9 +2854,7 @@ void Lexer::initKeywords()
|
|||||||
Token::tochars[TOKxorass] = "^=";
|
Token::tochars[TOKxorass] = "^=";
|
||||||
Token::tochars[TOKassign] = "=";
|
Token::tochars[TOKassign] = "=";
|
||||||
Token::tochars[TOKconstruct] = "=";
|
Token::tochars[TOKconstruct] = "=";
|
||||||
#if DMDV2
|
|
||||||
Token::tochars[TOKblit] = "=";
|
Token::tochars[TOKblit] = "=";
|
||||||
#endif
|
|
||||||
Token::tochars[TOKlt] = "<";
|
Token::tochars[TOKlt] = "<";
|
||||||
Token::tochars[TOKgt] = ">";
|
Token::tochars[TOKgt] = ">";
|
||||||
Token::tochars[TOKle] = "<=";
|
Token::tochars[TOKle] = "<=";
|
||||||
@@ -2993,13 +2923,11 @@ void Lexer::initKeywords()
|
|||||||
|
|
||||||
Token::tochars[TOKorass] = "|=";
|
Token::tochars[TOKorass] = "|=";
|
||||||
Token::tochars[TOKidentifier] = "identifier";
|
Token::tochars[TOKidentifier] = "identifier";
|
||||||
#if DMDV2
|
|
||||||
Token::tochars[TOKat] = "@";
|
Token::tochars[TOKat] = "@";
|
||||||
Token::tochars[TOKpow] = "^^";
|
Token::tochars[TOKpow] = "^^";
|
||||||
Token::tochars[TOKpowass] = "^^=";
|
Token::tochars[TOKpowass] = "^^=";
|
||||||
Token::tochars[TOKgoesto] = "=>";
|
Token::tochars[TOKgoesto] = "=>";
|
||||||
Token::tochars[TOKpound] = "#";
|
Token::tochars[TOKpound] = "#";
|
||||||
#endif
|
|
||||||
|
|
||||||
// For debugging
|
// For debugging
|
||||||
Token::tochars[TOKerror] = "error";
|
Token::tochars[TOKerror] = "error";
|
||||||
|
|||||||
+12
-15
@@ -126,7 +126,7 @@ enum TOK
|
|||||||
TOKfloat32, TOKfloat64, TOKfloat80,
|
TOKfloat32, TOKfloat64, TOKfloat80,
|
||||||
TOKimaginary32, TOKimaginary64, TOKimaginary80,
|
TOKimaginary32, TOKimaginary64, TOKimaginary80,
|
||||||
TOKcomplex32, TOKcomplex64, TOKcomplex80,
|
TOKcomplex32, TOKcomplex64, TOKcomplex80,
|
||||||
TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
|
TOKchar, TOKwchar, TOKdchar, TOKbool,
|
||||||
|
|
||||||
// 152
|
// 152
|
||||||
// Aggregates
|
// Aggregates
|
||||||
@@ -157,7 +157,7 @@ enum TOK
|
|||||||
TOKargTypes,
|
TOKargTypes,
|
||||||
TOKref,
|
TOKref,
|
||||||
TOKmacro,
|
TOKmacro,
|
||||||
#if DMDV2
|
|
||||||
TOKparameters,
|
TOKparameters,
|
||||||
TOKtraits,
|
TOKtraits,
|
||||||
TOKoverloadset,
|
TOKoverloadset,
|
||||||
@@ -176,7 +176,6 @@ enum TOK
|
|||||||
TOKgoesto,
|
TOKgoesto,
|
||||||
TOKvector,
|
TOKvector,
|
||||||
TOKpound,
|
TOKpound,
|
||||||
#endif
|
|
||||||
|
|
||||||
// LDC specific
|
// LDC specific
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
@@ -190,7 +189,7 @@ enum TOK
|
|||||||
|
|
||||||
#define BASIC_TYPES \
|
#define BASIC_TYPES \
|
||||||
TOKwchar: case TOKdchar: \
|
TOKwchar: case TOKdchar: \
|
||||||
case TOKbit: case TOKbool: case TOKchar: \
|
case TOKbool: case TOKchar: \
|
||||||
case TOKint8: case TOKuns8: \
|
case TOKint8: case TOKuns8: \
|
||||||
case TOKint16: case TOKuns16: \
|
case TOKint16: case TOKuns16: \
|
||||||
case TOKint32: case TOKuns32: \
|
case TOKint32: case TOKuns32: \
|
||||||
@@ -232,10 +231,10 @@ struct Token
|
|||||||
{
|
{
|
||||||
Token *next;
|
Token *next;
|
||||||
Loc loc;
|
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;
|
TOK value;
|
||||||
utf8_t *blockComment; // doc comment string prior to this token
|
const utf8_t *blockComment; // doc comment string prior to this token
|
||||||
utf8_t *lineComment; // doc comment for previous token
|
const utf8_t *lineComment; // doc comment for previous token
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
// Integers
|
// Integers
|
||||||
@@ -277,9 +276,9 @@ public:
|
|||||||
|
|
||||||
Loc scanloc; // for error messages
|
Loc scanloc; // for error messages
|
||||||
|
|
||||||
utf8_t *base; // pointer to start of buffer
|
const utf8_t *base; // pointer to start of buffer
|
||||||
utf8_t *end; // past end of buffer
|
const utf8_t *end; // past end of buffer
|
||||||
utf8_t *p; // current character
|
const utf8_t *p; // current character
|
||||||
Token token;
|
Token token;
|
||||||
Module *mod;
|
Module *mod;
|
||||||
int doDocComment; // collect doc comment information
|
int doDocComment; // collect doc comment information
|
||||||
@@ -287,7 +286,7 @@ public:
|
|||||||
int commentToken; // !=0 means comments are TOKcomment's
|
int commentToken; // !=0 means comments are TOKcomment's
|
||||||
|
|
||||||
Lexer(Module *mod,
|
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);
|
int doDocComment, int commentToken);
|
||||||
|
|
||||||
static void initKeywords();
|
static void initKeywords();
|
||||||
@@ -304,10 +303,8 @@ public:
|
|||||||
unsigned escapeSequence();
|
unsigned escapeSequence();
|
||||||
TOK wysiwygStringConstant(Token *t, int tc);
|
TOK wysiwygStringConstant(Token *t, int tc);
|
||||||
TOK hexStringConstant(Token *t);
|
TOK hexStringConstant(Token *t);
|
||||||
#if DMDV2
|
|
||||||
TOK delimitedStringConstant(Token *t);
|
TOK delimitedStringConstant(Token *t);
|
||||||
TOK tokenStringConstant(Token *t);
|
TOK tokenStringConstant(Token *t);
|
||||||
#endif
|
|
||||||
TOK escapeStringConstant(Token *t, int wide);
|
TOK escapeStringConstant(Token *t, int wide);
|
||||||
TOK charConstant(Token *t, int wide);
|
TOK charConstant(Token *t, int wide);
|
||||||
void stringPostfix(Token *t);
|
void stringPostfix(Token *t);
|
||||||
@@ -320,8 +317,8 @@ public:
|
|||||||
unsigned decodeUTF();
|
unsigned decodeUTF();
|
||||||
void getDocComment(Token *t, unsigned lineComment);
|
void getDocComment(Token *t, unsigned lineComment);
|
||||||
|
|
||||||
static int isValidIdentifier(char *p);
|
static int isValidIdentifier(const char *p);
|
||||||
static utf8_t *combineComments(utf8_t *c1, utf8_t *c2);
|
static const utf8_t *combineComments(const utf8_t *c1, const utf8_t *c2);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DMD_LEXER_H */
|
#endif /* DMD_LEXER_H */
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ class Library
|
|||||||
public:
|
public:
|
||||||
static Library *factory();
|
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 addObject(const char *module_name, void *buf, size_t buflen) = 0;
|
||||||
virtual void addLibrary(void *buf, size_t buflen) = 0;
|
virtual void addLibrary(void *buf, size_t buflen) = 0;
|
||||||
virtual void write() = 0;
|
virtual void write() = 0;
|
||||||
|
|||||||
+15
-15
@@ -21,16 +21,16 @@
|
|||||||
|
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
|
||||||
int isIdStart(utf8_t *p);
|
int isIdStart(const utf8_t *p);
|
||||||
int isIdTail(utf8_t *p);
|
int isIdTail(const utf8_t *p);
|
||||||
int utfStride(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);
|
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;
|
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;
|
{ Macro *table;
|
||||||
|
|
||||||
//printf("Macro::search(%.*s)\n", namelen, name);
|
//printf("Macro::search(%.*s)\n", namelen, name);
|
||||||
@@ -67,7 +67,7 @@ Macro *Macro::search(utf8_t *name, size_t namelen)
|
|||||||
return table;
|
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);
|
//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
|
* -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.
|
/* Scan forward for matching right parenthesis.
|
||||||
* Nest parentheses.
|
* 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,
|
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
|
#if 0
|
||||||
printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg);
|
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);
|
arg = memdup(arg, arglen);
|
||||||
for (size_t u = start; u + 1 < end; )
|
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.
|
/* 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];
|
utf8_t c = p[u + 1];
|
||||||
int n = (c == '+') ? -1 : c - '0';
|
int n = (c == '+') ? -1 : c - '0';
|
||||||
|
|
||||||
utf8_t *marg;
|
const utf8_t *marg;
|
||||||
size_t marglen;
|
size_t marglen;
|
||||||
extractArgN(arg, arglen, &marg, &marglen, n);
|
extractArgN(arg, arglen, &marg, &marglen, n);
|
||||||
if (marglen == 0)
|
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; )
|
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
|
/* A valid start of macro expansion is $(c, where c is
|
||||||
* an id start character, and not $$(c.
|
* 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;
|
utf8_t *name = p + u + 2;
|
||||||
size_t namelen = 0;
|
size_t namelen = 0;
|
||||||
|
|
||||||
utf8_t *marg;
|
const utf8_t *marg;
|
||||||
size_t marglen;
|
size_t marglen;
|
||||||
|
|
||||||
size_t v;
|
size_t v;
|
||||||
@@ -427,7 +427,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
|||||||
end -= v + 1 - u;
|
end -= v + 1 - u;
|
||||||
u += mend - (v + 1);
|
u += mend - (v + 1);
|
||||||
#endif
|
#endif
|
||||||
mem.free(marg);
|
mem.free((utf8_t *)marg);
|
||||||
//printf("u = %d, end = %d\n", u, end);
|
//printf("u = %d, end = %d\n", u, end);
|
||||||
//printf("#%.*s#\n", end - u, &buf->data[u]);
|
//printf("#%.*s#\n", end - u, &buf->data[u]);
|
||||||
continue;
|
continue;
|
||||||
@@ -444,7 +444,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
|||||||
}
|
}
|
||||||
u++;
|
u++;
|
||||||
}
|
}
|
||||||
mem.free(arg);
|
mem.free((utf8_t *)arg);
|
||||||
*pend = end;
|
*pend = end;
|
||||||
nest--;
|
nest--;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -24,22 +24,22 @@ struct Macro
|
|||||||
private:
|
private:
|
||||||
Macro *next; // next in list
|
Macro *next; // next in list
|
||||||
|
|
||||||
utf8_t *name; // macro name
|
const utf8_t *name; // macro name
|
||||||
size_t namelen; // length of 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
|
size_t textlen; // length of replacement text
|
||||||
|
|
||||||
int inuse; // macro is in use (don't expand)
|
int inuse; // macro is in use (don't expand)
|
||||||
|
|
||||||
Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen);
|
Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen);
|
||||||
Macro *search(utf8_t *name, size_t namelen);
|
Macro *search(const utf8_t *name, size_t namelen);
|
||||||
|
|
||||||
public:
|
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,
|
void expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||||
utf8_t *arg, size_t arglen);
|
const utf8_t *arg, size_t arglen);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+38
-44
@@ -67,7 +67,12 @@ char *mangle(Declaration *sthis, bool isv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf.prependstring("0");
|
buf.prependstring("0");
|
||||||
s = s->parent;
|
|
||||||
|
TemplateInstance *ti = s->isTemplateInstance();
|
||||||
|
if (ti && !ti->isTemplateMixin())
|
||||||
|
s = ti->tempdecl->parent;
|
||||||
|
else
|
||||||
|
s = s->parent;
|
||||||
} while (s);
|
} while (s);
|
||||||
|
|
||||||
// buf.prependstring("_D");
|
// buf.prependstring("_D");
|
||||||
@@ -118,23 +123,9 @@ L1:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *Declaration::mangle(bool isv)
|
const char *Declaration::mangle(bool isv)
|
||||||
#if __DMC__
|
{
|
||||||
__out(result)
|
char *p;
|
||||||
{
|
|
||||||
int len = strlen(result);
|
|
||||||
|
|
||||||
assert(len > 0);
|
|
||||||
//printf("mangle: '%s' => '%s'\n", toChars(), result);
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
assert(result[i] == '_' ||
|
|
||||||
result[i] == '@' ||
|
|
||||||
isalnum(result[i]) || result[i] & 0x80);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__body
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage);
|
//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
|
if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope
|
||||||
{
|
{
|
||||||
@@ -150,34 +141,52 @@ const char *Declaration::mangle(bool isv)
|
|||||||
case LINKc:
|
case LINKc:
|
||||||
case LINKwindows:
|
case LINKwindows:
|
||||||
case LINKpascal:
|
case LINKpascal:
|
||||||
return ident->toChars();
|
p = ident->toChars();
|
||||||
|
goto Lret;
|
||||||
|
|
||||||
case LINKcpp:
|
case LINKcpp:
|
||||||
#if CPP_MANGLE
|
#if CPP_MANGLE
|
||||||
return cpp_mangle(this);
|
p = cpp_mangle(this);
|
||||||
#else
|
#else
|
||||||
// Windows C++ mangling is done by C++ back end
|
// Windows C++ mangling is done by C++ back end
|
||||||
return ident->toChars();
|
p = ident->toChars();
|
||||||
#endif
|
#endif
|
||||||
|
goto Lret;
|
||||||
|
|
||||||
case LINKdefault:
|
case LINKdefault:
|
||||||
error("forward declaration");
|
error("forward declaration");
|
||||||
return ident->toChars();
|
p = ident->toChars();
|
||||||
|
goto Lret;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "'%s', linkage = %d\n", toChars(), linkage);
|
fprintf(stderr, "'%s', linkage = %d\n", toChars(), linkage);
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char *p = ::mangle(this, isv);
|
{
|
||||||
|
p = ::mangle(this, isv);
|
||||||
OutBuffer buf;
|
OutBuffer buf;
|
||||||
buf.writestring("_D");
|
buf.writestring("_D");
|
||||||
buf.writestring(p);
|
buf.writestring(p);
|
||||||
p = buf.toChars();
|
p = buf.toChars();
|
||||||
buf.data = NULL;
|
buf.data = NULL;
|
||||||
|
}
|
||||||
//printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p);
|
//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;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Normally FuncDeclaration and FuncAliasDeclaration have overloads.
|
* Normally FuncDeclaration and FuncAliasDeclaration have overloads.
|
||||||
@@ -222,14 +231,7 @@ const char *FuncAliasDeclaration::mangle(bool isv)
|
|||||||
* Returns exact mangled name of function.
|
* Returns exact mangled name of function.
|
||||||
*/
|
*/
|
||||||
const char *FuncDeclaration::mangleExact(bool isv)
|
const char *FuncDeclaration::mangleExact(bool isv)
|
||||||
#if __DMC__
|
{
|
||||||
__out(result)
|
|
||||||
{
|
|
||||||
assert(strlen(result) > 0);
|
|
||||||
}
|
|
||||||
__body
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
assert(!isFuncAliasDeclaration());
|
assert(!isFuncAliasDeclaration());
|
||||||
|
|
||||||
if (mangleOverride)
|
if (mangleOverride)
|
||||||
@@ -243,22 +245,15 @@ const char *FuncDeclaration::mangleExact(bool isv)
|
|||||||
|
|
||||||
assert(this);
|
assert(this);
|
||||||
return Declaration::mangle(isv);
|
return Declaration::mangle(isv);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *VarDeclaration::mangle(bool isv)
|
const char *VarDeclaration::mangle(bool isv)
|
||||||
#if __DMC__
|
{
|
||||||
__out(result)
|
|
||||||
{
|
|
||||||
assert(strlen(result) > 0);
|
|
||||||
}
|
|
||||||
__body
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (mangleOverride)
|
if (mangleOverride)
|
||||||
return mangleOverride;
|
return mangleOverride;
|
||||||
|
|
||||||
return Declaration::mangle();
|
return Declaration::mangle();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *TypedefDeclaration::mangle(bool isv)
|
const char *TypedefDeclaration::mangle(bool isv)
|
||||||
{
|
{
|
||||||
@@ -269,7 +264,6 @@ const char *TypedefDeclaration::mangle(bool isv)
|
|||||||
|
|
||||||
const char *AggregateDeclaration::mangle(bool isv)
|
const char *AggregateDeclaration::mangle(bool isv)
|
||||||
{
|
{
|
||||||
#if 1
|
|
||||||
//printf("AggregateDeclaration::mangle() '%s'\n", toChars());
|
//printf("AggregateDeclaration::mangle() '%s'\n", toChars());
|
||||||
if (Dsymbol *p = toParent2())
|
if (Dsymbol *p = toParent2())
|
||||||
{ if (FuncDeclaration *fd = p->isFuncDeclaration())
|
{ if (FuncDeclaration *fd = p->isFuncDeclaration())
|
||||||
@@ -279,7 +273,7 @@ const char *AggregateDeclaration::mangle(bool isv)
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return Dsymbol::mangle(isv);
|
return Dsymbol::mangle(isv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +335,7 @@ const char *TemplateInstance::mangle(bool isv)
|
|||||||
error("is not defined");
|
error("is not defined");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Dsymbol *par = enclosing || isTemplateMixin() ? parent : tempdecl->parent;
|
Dsymbol *par = isTemplateMixin() ? parent : tempdecl->parent;
|
||||||
if (par)
|
if (par)
|
||||||
{
|
{
|
||||||
const char *p = par->mangle(isv);
|
const char *p = par->mangle(isv);
|
||||||
|
|||||||
+55
-109
@@ -47,9 +47,9 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !IN_LLVM
|
#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 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_start(char *srcfile);
|
||||||
void obj_end(Library *library, File *objfile);
|
void obj_end(Library *library, File *objfile);
|
||||||
@@ -57,7 +57,7 @@ void obj_end(Library *library, File *objfile);
|
|||||||
|
|
||||||
void printCtfePerformanceStats();
|
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 */
|
/** Normalize path by turning forward slashes into backslashes */
|
||||||
void toWinPath(char *src)
|
void toWinPath(char *src)
|
||||||
@@ -384,7 +384,7 @@ Usage:\n\
|
|||||||
-debuglib=name set symbolic debug library to name\n\
|
-debuglib=name set symbolic debug library to name\n\
|
||||||
-defaultlib=name set default library to name\n\
|
-defaultlib=name set default library to name\n\
|
||||||
-deps print module dependencies (imports/file/version/debug/lib)\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\
|
-g add symbolic debug info\n\
|
||||||
-gc add symbolic debug info, pretend to be C\n\
|
-gc add symbolic debug info, pretend to be C\n\
|
||||||
-gs always emit stack frame\n\
|
-gs always emit stack frame\n\
|
||||||
@@ -432,14 +432,6 @@ Usage:\n\
|
|||||||
|
|
||||||
extern signed char tyalignsize[];
|
extern signed char tyalignsize[];
|
||||||
|
|
||||||
#if _WIN32 && __DMC__
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
extern int _xi_a;
|
|
||||||
extern int _end;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static Module *entrypoint = NULL;
|
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.
|
/* 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()
|
* 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 _d_run_main(int argc, char **argv, void* mainFunc);\n\
|
||||||
int _Dmain(char[][] args);\n\
|
int _Dmain(char[][] args);\n\
|
||||||
int main(int argc, char **argv) { return _d_run_main(argc, argv, &_Dmain); }\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;
|
Identifier *id = Id::entrypoint;
|
||||||
Module *m = new Module("__entrypoint.d", id, 0, 0);
|
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.scanloc = Loc();
|
||||||
p.nextToken();
|
p.nextToken();
|
||||||
m->members = p.parseModule();
|
m->members = p.parseModule();
|
||||||
@@ -486,18 +478,10 @@ void genCmain(Scope *sc)
|
|||||||
entrypoint = m;
|
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 files;
|
||||||
Strings libmodules;
|
Strings libmodules;
|
||||||
char *p;
|
|
||||||
Module *m;
|
|
||||||
size_t argcstart = argc;
|
size_t argcstart = argc;
|
||||||
int setdebuglib = 0;
|
int setdebuglib = 0;
|
||||||
char noboundscheck = 0;
|
char noboundscheck = 0;
|
||||||
@@ -552,7 +536,7 @@ int tryMain(size_t argc, char *argv[])
|
|||||||
global.params.is64bit = (sizeof(size_t) == 8);
|
global.params.is64bit = (sizeof(size_t) == 8);
|
||||||
|
|
||||||
#if TARGET_WINDOS
|
#if TARGET_WINDOS
|
||||||
global.params.is64bit = 0;
|
global.params.is64bit = false;
|
||||||
global.params.defaultlibname = "phobos";
|
global.params.defaultlibname = "phobos";
|
||||||
#elif TARGET_LINUX
|
#elif TARGET_LINUX
|
||||||
global.params.defaultlibname = "libphobos2.a";
|
global.params.defaultlibname = "libphobos2.a";
|
||||||
@@ -597,9 +581,7 @@ int tryMain(size_t argc, char *argv[])
|
|||||||
|
|
||||||
VersionCondition::addPredefinedGlobalIdent("LittleEndian");
|
VersionCondition::addPredefinedGlobalIdent("LittleEndian");
|
||||||
//VersionCondition::addPredefinedGlobalIdent("D_Bits");
|
//VersionCondition::addPredefinedGlobalIdent("D_Bits");
|
||||||
#if DMDV2
|
|
||||||
VersionCondition::addPredefinedGlobalIdent("D_Version2");
|
VersionCondition::addPredefinedGlobalIdent("D_Version2");
|
||||||
#endif
|
|
||||||
VersionCondition::addPredefinedGlobalIdent("all");
|
VersionCondition::addPredefinedGlobalIdent("all");
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
@@ -611,7 +593,7 @@ int tryMain(size_t argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t dflags_argc = 0;
|
size_t dflags_argc = 0;
|
||||||
char** dflags_argv = NULL;
|
const char** dflags_argv = NULL;
|
||||||
getenv_setargv("DFLAGS", &dflags_argc, &dflags_argv);
|
getenv_setargv("DFLAGS", &dflags_argc, &dflags_argv);
|
||||||
|
|
||||||
bool is64bit = global.params.is64bit; // use default
|
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);
|
is64bit = parse_arch(dflags_argc, dflags_argv, is64bit);
|
||||||
global.params.is64bit = 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);
|
getenv_setargv("DFLAGS", &argc, &argv);
|
||||||
|
|
||||||
@@ -632,7 +615,7 @@ int tryMain(size_t argc, char *argv[])
|
|||||||
|
|
||||||
for (size_t i = 1; i < argc; i++)
|
for (size_t i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
p = argv[i];
|
const char *p = argv[i];
|
||||||
if (*p == '-')
|
if (*p == '-')
|
||||||
{
|
{
|
||||||
if (strcmp(p + 1, "allinst") == 0)
|
if (strcmp(p + 1, "allinst") == 0)
|
||||||
@@ -657,10 +640,10 @@ int tryMain(size_t argc, char *argv[])
|
|||||||
{ long percent;
|
{ long percent;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
percent = strtol(p + 5, &p, 10);
|
percent = strtol(p + 5, (char **)&p, 10);
|
||||||
if (*p || errno || percent > 100)
|
if (*p || errno || percent > 100)
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
global.params.covPercent = percent;
|
global.params.covPercent = (unsigned char)percent;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
@@ -704,14 +687,13 @@ int tryMain(size_t argc, char *argv[])
|
|||||||
global.params.trace = 1;
|
global.params.trace = 1;
|
||||||
}
|
}
|
||||||
else if (strcmp(p + 1, "m32") == 0)
|
else if (strcmp(p + 1, "m32") == 0)
|
||||||
global.params.is64bit = 0;
|
global.params.is64bit = false;
|
||||||
else if (strcmp(p + 1, "m64") == 0)
|
else if (strcmp(p + 1, "m64") == 0)
|
||||||
global.params.is64bit = 1;
|
global.params.is64bit = true;
|
||||||
else if (strcmp(p + 1, "profile") == 0)
|
else if (strcmp(p + 1, "profile") == 0)
|
||||||
global.params.trace = 1;
|
global.params.trace = 1;
|
||||||
else if (strcmp(p + 1, "v") == 0)
|
else if (strcmp(p + 1, "v") == 0)
|
||||||
global.params.verbose = 1;
|
global.params.verbose = 1;
|
||||||
#if DMDV2
|
|
||||||
else if (strcmp(p + 1, "vtls") == 0)
|
else if (strcmp(p + 1, "vtls") == 0)
|
||||||
global.params.vtls = 1;
|
global.params.vtls = 1;
|
||||||
else if (memcmp(p + 1, "transition", 10) == 0)
|
else if (memcmp(p + 1, "transition", 10) == 0)
|
||||||
@@ -740,7 +722,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
{ long num;
|
{ long num;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
num = strtol(p + 12, &p, 10);
|
num = strtol(p + 12, (char **)&p, 10);
|
||||||
if (*p || errno || num > INT_MAX)
|
if (*p || errno || num > INT_MAX)
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
switch (num) // Bugzilla issue number
|
switch (num) // Bugzilla issue number
|
||||||
@@ -767,7 +749,6 @@ Language changes listed by -transition=id:\n\
|
|||||||
else
|
else
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else if (strcmp(p + 1, "w") == 0)
|
else if (strcmp(p + 1, "w") == 0)
|
||||||
global.params.warnings = 1;
|
global.params.warnings = 1;
|
||||||
else if (strcmp(p + 1, "wi") == 0)
|
else if (strcmp(p + 1, "wi") == 0)
|
||||||
@@ -786,7 +767,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
if (!p[3])
|
if (!p[3])
|
||||||
goto Lnoarg;
|
goto Lnoarg;
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
toWinPath(p + 3);
|
toWinPath((char *)p + 3);
|
||||||
#endif
|
#endif
|
||||||
global.params.objdir = p + 3;
|
global.params.objdir = p + 3;
|
||||||
break;
|
break;
|
||||||
@@ -795,7 +776,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
if (!p[3])
|
if (!p[3])
|
||||||
goto Lnoarg;
|
goto Lnoarg;
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
toWinPath(p + 3);
|
toWinPath((char *)p + 3);
|
||||||
#endif
|
#endif
|
||||||
global.params.objname = p + 3;
|
global.params.objname = p + 3;
|
||||||
break;
|
break;
|
||||||
@@ -892,10 +873,8 @@ Language changes listed by -transition=id:\n\
|
|||||||
global.params.release = 1;
|
global.params.release = 1;
|
||||||
else if (strcmp(p + 1, "betterC") == 0)
|
else if (strcmp(p + 1, "betterC") == 0)
|
||||||
global.params.betterC = 1;
|
global.params.betterC = 1;
|
||||||
#if DMDV2
|
|
||||||
else if (strcmp(p + 1, "noboundscheck") == 0)
|
else if (strcmp(p + 1, "noboundscheck") == 0)
|
||||||
noboundscheck = 1;
|
noboundscheck = 1;
|
||||||
#endif
|
|
||||||
else if (strcmp(p + 1, "unittest") == 0)
|
else if (strcmp(p + 1, "unittest") == 0)
|
||||||
global.params.useUnitTests = 1;
|
global.params.useUnitTests = 1;
|
||||||
else if (p[1] == 'I')
|
else if (p[1] == 'I')
|
||||||
@@ -922,7 +901,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
{ long level;
|
{ long level;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
level = strtol(p + 7, &p, 10);
|
level = strtol(p + 7, (char **)&p, 10);
|
||||||
if (*p || errno || level > INT_MAX)
|
if (*p || errno || level > INT_MAX)
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
DebugCondition::setGlobalLevel((int)level);
|
DebugCondition::setGlobalLevel((int)level);
|
||||||
@@ -948,7 +927,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
{ long level;
|
{ long level;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
level = strtol(p + 9, &p, 10);
|
level = strtol(p + 9, (char **)&p, 10);
|
||||||
if (*p || errno || level > INT_MAX)
|
if (*p || errno || level > INT_MAX)
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
VersionCondition::setGlobalLevel((int)level);
|
VersionCondition::setGlobalLevel((int)level);
|
||||||
@@ -1017,39 +996,19 @@ Language changes listed by -transition=id:\n\
|
|||||||
else if (memcmp(p + 1, "man", 3) == 0)
|
else if (memcmp(p + 1, "man", 3) == 0)
|
||||||
{
|
{
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#if DMDV1
|
|
||||||
browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
|
|
||||||
#else
|
|
||||||
browse("http://dlang.org/dmd-windows.html");
|
browse("http://dlang.org/dmd-windows.html");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#if linux
|
#if linux
|
||||||
#if DMDV1
|
|
||||||
browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
|
|
||||||
#else
|
|
||||||
browse("http://dlang.org/dmd-linux.html");
|
browse("http://dlang.org/dmd-linux.html");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
#if DMDV1
|
|
||||||
browse("http://www.digitalmars.com/d/1.0/dmd-osx.html");
|
|
||||||
#else
|
|
||||||
browse("http://dlang.org/dmd-osx.html");
|
browse("http://dlang.org/dmd-osx.html");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#if __FreeBSD__
|
#if __FreeBSD__
|
||||||
#if DMDV1
|
|
||||||
browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html");
|
|
||||||
#else
|
|
||||||
browse("http://dlang.org/dmd-freebsd.html");
|
browse("http://dlang.org/dmd-freebsd.html");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#if __OpenBSD__
|
#if __OpenBSD__
|
||||||
#if DMDV1
|
|
||||||
browse("http://www.digitalmars.com/d/1.0/dmd-openbsd.html");
|
|
||||||
#else
|
|
||||||
browse("http://dlang.org/dmd-openbsd.html");
|
browse("http://dlang.org/dmd-openbsd.html");
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -1103,7 +1062,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
|
|
||||||
if(global.params.is64bit != is64bit)
|
if(global.params.is64bit != is64bit)
|
||||||
error(Loc(), "the architecture must not be changed in the %s section of %s",
|
error(Loc(), "the architecture must not be changed in the %s section of %s",
|
||||||
is64bit ? "Environment64" : "Environment32", inifilename);
|
envsec, inifilename);
|
||||||
|
|
||||||
// Target uses 64bit pointers.
|
// Target uses 64bit pointers.
|
||||||
global.params.isLP64 = global.params.is64bit;
|
global.params.isLP64 = global.params.is64bit;
|
||||||
@@ -1175,15 +1134,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
global.params.objname = NULL;
|
global.params.objname = NULL;
|
||||||
|
|
||||||
// Haven't investigated handling these options with multiobj
|
// Haven't investigated handling these options with multiobj
|
||||||
if (!global.params.cov && !global.params.trace
|
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
|
|
||||||
)
|
|
||||||
global.params.multiobj = 1;
|
global.params.multiobj = 1;
|
||||||
}
|
}
|
||||||
else if (global.params.run)
|
else if (global.params.run)
|
||||||
@@ -1234,14 +1185,12 @@ Language changes listed by -transition=id:\n\
|
|||||||
VersionCondition::addPredefinedGlobalIdent("D_Coverage");
|
VersionCondition::addPredefinedGlobalIdent("D_Coverage");
|
||||||
if (global.params.pic)
|
if (global.params.pic)
|
||||||
VersionCondition::addPredefinedGlobalIdent("D_PIC");
|
VersionCondition::addPredefinedGlobalIdent("D_PIC");
|
||||||
#if DMDV2
|
|
||||||
if (global.params.useUnitTests)
|
if (global.params.useUnitTests)
|
||||||
VersionCondition::addPredefinedGlobalIdent("unittest");
|
VersionCondition::addPredefinedGlobalIdent("unittest");
|
||||||
if (global.params.useAssert)
|
if (global.params.useAssert)
|
||||||
VersionCondition::addPredefinedGlobalIdent("assert");
|
VersionCondition::addPredefinedGlobalIdent("assert");
|
||||||
if (noboundscheck)
|
if (noboundscheck)
|
||||||
VersionCondition::addPredefinedGlobalIdent("D_NoBoundsChecks");
|
VersionCondition::addPredefinedGlobalIdent("D_NoBoundsChecks");
|
||||||
#endif
|
|
||||||
|
|
||||||
VersionCondition::addPredefinedGlobalIdent("D_HardFloat");
|
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++)
|
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);
|
Strings *a = FileName::splitPath(path);
|
||||||
|
|
||||||
if (a)
|
if (a)
|
||||||
@@ -1283,7 +1232,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < global.params.fileImppath->dim; i++)
|
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);
|
Strings *a = FileName::splitPath(path);
|
||||||
|
|
||||||
if (a)
|
if (a)
|
||||||
@@ -1306,22 +1255,18 @@ Language changes listed by -transition=id:\n\
|
|||||||
bool firstmodule = true;
|
bool firstmodule = true;
|
||||||
for (size_t i = 0; i < files.dim; i++)
|
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
|
#if _WIN32
|
||||||
// Convert / to \ so linker will work
|
toWinPath((char *)p);
|
||||||
for (size_t j = 0; p[j]; j++)
|
|
||||||
{
|
|
||||||
if (p[j] == '/')
|
|
||||||
p[j] = '\\';
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
p = (char *)FileName::name(p); // strip path
|
p = FileName::name(p); // strip path
|
||||||
ext = FileName::ext(p);
|
const char *ext = FileName::ext(p);
|
||||||
|
char *newname;
|
||||||
if (ext)
|
if (ext)
|
||||||
{ /* Deduce what to do with a file based on its extension
|
{ /* 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 '.'
|
ext--; // skip onto '.'
|
||||||
assert(*ext == '.');
|
assert(*ext == '.');
|
||||||
name = (char *)mem.malloc((ext - p) + 1);
|
newname = (char *)mem.malloc((ext - p) + 1);
|
||||||
memcpy(name, p, ext - p);
|
memcpy(newname, p, ext - p);
|
||||||
name[ext - p] = 0; // strip extension
|
newname[ext - p] = 0; // strip extension
|
||||||
|
name = newname;
|
||||||
|
|
||||||
if (name[0] == 0 ||
|
if (name[0] == 0 ||
|
||||||
strcmp(name, "..") == 0 ||
|
strcmp(name, "..") == 0 ||
|
||||||
@@ -1415,11 +1361,11 @@ Language changes listed by -transition=id:\n\
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Identifier *id = Lexer::idPool(name);
|
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);
|
modules.push(m);
|
||||||
|
|
||||||
if (firstmodule)
|
if (firstmodule)
|
||||||
{ global.params.objfiles->push((char *)m->objfile->name->str);
|
{ global.params.objfiles->push(m->objfile->name->str);
|
||||||
firstmodule = false;
|
firstmodule = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1450,7 +1396,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
AsyncRead *aw = AsyncRead::create(modules.dim);
|
AsyncRead *aw = AsyncRead::create(modules.dim);
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
aw->addFile(m->srcfile);
|
aw->addFile(m->srcfile);
|
||||||
}
|
}
|
||||||
aw->start();
|
aw->start();
|
||||||
@@ -1458,7 +1404,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
// Single threaded
|
// Single threaded
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
m->read(Loc());
|
m->read(Loc());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1468,7 +1414,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
size_t filecount = modules.dim;
|
size_t filecount = modules.dim;
|
||||||
for (size_t filei = 0, modi = 0; filei < filecount; filei++, modi++)
|
for (size_t filei = 0, modi = 0; filei < filecount; filei++, modi++)
|
||||||
{
|
{
|
||||||
m = modules[modi];
|
Module *m = modules[modi];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "parse %s\n", m->toChars());
|
fprintf(global.stdmsg, "parse %s\n", m->toChars());
|
||||||
if (!Module::rootModule)
|
if (!Module::rootModule)
|
||||||
@@ -1528,7 +1474,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
*/
|
*/
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "import %s\n", m->toChars());
|
fprintf(global.stdmsg, "import %s\n", m->toChars());
|
||||||
m->genhdrfile();
|
m->genhdrfile();
|
||||||
@@ -1540,7 +1486,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
// load all unconditional imports for better symbol resolving
|
// load all unconditional imports for better symbol resolving
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "importall %s\n", m->toChars());
|
fprintf(global.stdmsg, "importall %s\n", m->toChars());
|
||||||
m->importAll(NULL);
|
m->importAll(NULL);
|
||||||
@@ -1553,7 +1499,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
// Do semantic analysis
|
// Do semantic analysis
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "semantic %s\n", m->toChars());
|
fprintf(global.stdmsg, "semantic %s\n", m->toChars());
|
||||||
m->semantic();
|
m->semantic();
|
||||||
@@ -1567,7 +1513,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
// Do pass 2 semantic analysis
|
// Do pass 2 semantic analysis
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "semantic2 %s\n", m->toChars());
|
fprintf(global.stdmsg, "semantic2 %s\n", m->toChars());
|
||||||
m->semantic2();
|
m->semantic2();
|
||||||
@@ -1578,7 +1524,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
// Do pass 3 semantic analysis
|
// Do pass 3 semantic analysis
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
|
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
|
||||||
m->semantic3();
|
m->semantic3();
|
||||||
@@ -1599,7 +1545,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
// since otherwise functions in them cannot be inlined
|
// since otherwise functions in them cannot be inlined
|
||||||
for (size_t i = 0; i < Module::amodules.dim; i++)
|
for (size_t i = 0; i < Module::amodules.dim; i++)
|
||||||
{
|
{
|
||||||
m = Module::amodules[i];
|
Module *m = Module::amodules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
|
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
|
||||||
m->semantic3();
|
m->semantic3();
|
||||||
@@ -1630,7 +1576,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "inline scan %s\n", m->toChars());
|
fprintf(global.stdmsg, "inline scan %s\n", m->toChars());
|
||||||
m->inlineScan();
|
m->inlineScan();
|
||||||
@@ -1652,7 +1598,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
// Add input object and input library files to output library
|
// Add input object and input library files to output library
|
||||||
for (size_t i = 0; i < libmodules.dim; i++)
|
for (size_t i = 0; i < libmodules.dim; i++)
|
||||||
{
|
{
|
||||||
char *p = libmodules[i];
|
const char *p = libmodules[i];
|
||||||
library->addObject(p, NULL, 0);
|
library->addObject(p, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1711,7 +1657,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
obj_start(modules[0]->srcfile->toChars());
|
obj_start(modules[0]->srcfile->toChars());
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
||||||
m->genobjfile(0);
|
m->genobjfile(0);
|
||||||
@@ -1729,7 +1675,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < modules.dim; i++)
|
for (size_t i = 0; i < modules.dim; i++)
|
||||||
{
|
{
|
||||||
m = modules[i];
|
Module *m = modules[i];
|
||||||
if (global.params.verbose)
|
if (global.params.verbose)
|
||||||
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
||||||
if (global.params.obj)
|
if (global.params.obj)
|
||||||
@@ -1794,7 +1740,7 @@ Language changes listed by -transition=id:\n\
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
int status = -1;
|
int status = -1;
|
||||||
#if WINDOWS_SEH
|
#if WINDOWS_SEH
|
||||||
@@ -1821,7 +1767,7 @@ int main(int argc, char *argv[])
|
|||||||
* The string is separated into arguments, processing \ and ".
|
* 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;
|
char *p;
|
||||||
|
|
||||||
@@ -1965,10 +1911,10 @@ void escapePath(OutBuffer *buf, const char *fname)
|
|||||||
* to detect the desired architecture.
|
* 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)
|
for (size_t i = 0; i < argc; ++i)
|
||||||
{ char* p = argv[i];
|
{ const char* p = argv[i];
|
||||||
if (p[0] == '-')
|
if (p[0] == '-')
|
||||||
{
|
{
|
||||||
if (strcmp(p + 1, "m32") == 0)
|
if (strcmp(p + 1, "m32") == 0)
|
||||||
|
|||||||
+46
-45
@@ -96,12 +96,12 @@ void unittests();
|
|||||||
|
|
||||||
#define DMDV1 0
|
#define DMDV1 0
|
||||||
#define DMDV2 1 // Version 2.0 features
|
#define DMDV2 1 // Version 2.0 features
|
||||||
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
|
#define SNAN_DEFAULT_INIT 1 // if floats are default initialized to signalling NaN
|
||||||
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
|
#define MODULEINFO_IS_STRUCT 1 // if ModuleInfo is a struct rather than a class
|
||||||
#define PULL93 0 // controversial pull #93 for bugzilla 3449
|
#define PULL93 0 // controversial pull #93 for bugzilla 3449
|
||||||
|
|
||||||
// Set if C++ mangling is done by the front end
|
// 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
|
/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD, TARGET_OPENBSD and
|
||||||
* TARGET_SOLARIS, which are
|
* TARGET_SOLARIS, which are
|
||||||
@@ -135,7 +135,7 @@ struct OutBuffer;
|
|||||||
// Can't include arraytypes.h here, need to declare these directly.
|
// Can't include arraytypes.h here, need to declare these directly.
|
||||||
template <typename TYPE> struct Array;
|
template <typename TYPE> struct Array;
|
||||||
typedef Array<class Identifier> Identifiers;
|
typedef Array<class Identifier> Identifiers;
|
||||||
typedef Array<char> Strings;
|
typedef Array<const char> Strings;
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
enum OUTPUTFLAG
|
enum OUTPUTFLAG
|
||||||
@@ -151,9 +151,9 @@ typedef unsigned char ubyte;
|
|||||||
// Put command line switches in here
|
// Put command line switches in here
|
||||||
struct Param
|
struct Param
|
||||||
{
|
{
|
||||||
|
#if IN_LLVM
|
||||||
bool obj; // write object file
|
bool obj; // write object file
|
||||||
bool link; // perform link
|
bool link; // perform link
|
||||||
#if IN_LLVM
|
|
||||||
bool verbose; // verbose compile
|
bool verbose; // verbose compile
|
||||||
bool vtls; // identify thread local variables
|
bool vtls; // identify thread local variables
|
||||||
bool vfield; // identify non-mutable field variables
|
bool vfield; // identify non-mutable field variables
|
||||||
@@ -168,6 +168,8 @@ struct Param
|
|||||||
bool isOpenBSD; // generate code for OpenBSD
|
bool isOpenBSD; // generate code for OpenBSD
|
||||||
bool isSolaris; // generate code for Solaris
|
bool isSolaris; // generate code for Solaris
|
||||||
#else
|
#else
|
||||||
|
char obj; // write object file
|
||||||
|
char link; // perform link
|
||||||
char dll; // generate shared dynamic library
|
char dll; // generate shared dynamic library
|
||||||
char lib; // write library file instead of object file(s)
|
char lib; // write library file instead of object file(s)
|
||||||
char multiobj; // break one object file into multiple ones
|
char multiobj; // break one object file into multiple ones
|
||||||
@@ -181,7 +183,7 @@ struct Param
|
|||||||
bool alwaysframe; // always emit standard stack frame
|
bool alwaysframe; // always emit standard stack frame
|
||||||
bool optimize; // run optimizer
|
bool optimize; // run optimizer
|
||||||
char map; // generate linker .map file
|
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 isLP64; // generate code for LP64
|
||||||
char isLinux; // generate code for linux
|
char isLinux; // generate code for linux
|
||||||
char isOSX; // generate code for Mac OSX
|
char isOSX; // generate code for Mac OSX
|
||||||
@@ -217,8 +219,6 @@ struct Param
|
|||||||
ubyte Dversion; // D version number
|
ubyte Dversion; // D version number
|
||||||
bool ignoreUnsupportedPragmas; // rather than error on them
|
bool ignoreUnsupportedPragmas; // rather than error on them
|
||||||
bool enforcePropertySyntax;
|
bool enforcePropertySyntax;
|
||||||
bool addMain; // LDC_FIXME: Implement.
|
|
||||||
bool allInst; // LDC_FIXME: Implement.
|
|
||||||
#else
|
#else
|
||||||
bool pic; // generate position-independent-code for shared libs
|
bool pic; // generate position-independent-code for shared libs
|
||||||
bool cov; // generate code coverage data
|
bool cov; // generate code coverage data
|
||||||
@@ -227,38 +227,51 @@ struct Param
|
|||||||
char ignoreUnsupportedPragmas; // rather than error on them
|
char ignoreUnsupportedPragmas; // rather than error on them
|
||||||
char enforcePropertySyntax;
|
char enforcePropertySyntax;
|
||||||
char betterC; // be a "better C" compiler; no dependency on D runtime
|
char betterC; // be a "better C" compiler; no dependency on D runtime
|
||||||
|
#endif
|
||||||
bool addMain; // add a default main() function
|
bool addMain; // add a default main() function
|
||||||
bool allInst; // generate code for all template instantiations
|
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 *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
|
Strings *fileImppath; // array of char*'s of where to look for file import modules
|
||||||
char *objdir; // .obj/.lib file output directory
|
const char *objdir; // .obj/.lib file output directory
|
||||||
char *objname; // .obj file output name
|
const char *objname; // .obj file output name
|
||||||
|
const char *libname; // .lib file output name
|
||||||
|
|
||||||
bool doDocComments; // process embedded documentation comments
|
#if IN_LLVM
|
||||||
char *docdir; // write documentation file to docdir directory
|
bool doDocComments; // process embedded documentation comments
|
||||||
char *docname; // write documentation file to docname
|
#else
|
||||||
Strings *ddocfiles; // macro include files for Ddoc
|
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
|
#if IN_LLVM
|
||||||
char *hdrdir; // write 'header' file to docdir directory
|
bool doHdrGeneration; // process embedded documentation comments
|
||||||
char *hdrname; // write 'header' file to docname
|
#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
|
#if IN_LLVM
|
||||||
char *xfilename; // write JSON file to xfilename
|
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
|
Strings *debugids; // debug identifiers
|
||||||
|
|
||||||
unsigned versionlevel; // version level
|
unsigned versionlevel; // version level
|
||||||
Strings *versionids; // version identifiers
|
Strings *versionids; // version identifiers
|
||||||
|
|
||||||
Strings *defaultlibnames; // default libraries for non-debug builds
|
Strings *defaultlibnames; // default libraries for non-debug builds
|
||||||
Strings *debuglibnames; // default libraries for 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
|
OutBuffer *moduleDeps; // contents to be written to deps file
|
||||||
|
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
@@ -276,17 +289,17 @@ struct Param
|
|||||||
bool run; // run resulting executable
|
bool run; // run resulting executable
|
||||||
#if !IN_LLVM
|
#if !IN_LLVM
|
||||||
size_t runargs_length;
|
size_t runargs_length;
|
||||||
char** runargs; // arguments for executable
|
const char** runargs; // arguments for executable
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Linker stuff
|
// Linker stuff
|
||||||
Strings *objfiles;
|
Strings *objfiles;
|
||||||
Strings *linkswitches;
|
Strings *linkswitches;
|
||||||
Strings *libfiles;
|
Strings *libfiles;
|
||||||
char *deffile;
|
const char *deffile;
|
||||||
char *resfile;
|
const char *resfile;
|
||||||
char *exefile;
|
const char *exefile;
|
||||||
char *mapfile;
|
const char *mapfile;
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
// Whether to keep all function bodies in .di file generation or to strip
|
// 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
|
// those of plain functions. For DMD, this is govenered by the -inline
|
||||||
@@ -399,12 +412,7 @@ extern Global global;
|
|||||||
|
|
||||||
#include "longdouble.h"
|
#include "longdouble.h"
|
||||||
|
|
||||||
#ifdef __DMC__
|
#include "complex_t.h"
|
||||||
#include <complex.h>
|
|
||||||
typedef _Complex long double complex_t;
|
|
||||||
#else
|
|
||||||
#include "complex_t.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Be careful not to care about sign when using dinteger_t
|
// Be careful not to care about sign when using dinteger_t
|
||||||
//typedef uint64_t integer_t;
|
//typedef uint64_t integer_t;
|
||||||
@@ -455,13 +463,6 @@ struct Loc
|
|||||||
bool equals(const Loc& 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
|
#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry
|
||||||
// in interface vtbl[]'s
|
// in interface vtbl[]'s
|
||||||
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears
|
||||||
@@ -497,9 +498,7 @@ enum MATCH
|
|||||||
{
|
{
|
||||||
MATCHnomatch, // no match
|
MATCHnomatch, // no match
|
||||||
MATCHconvert, // match with conversions
|
MATCHconvert, // match with conversions
|
||||||
#if DMDV2
|
|
||||||
MATCHconst, // match with conversion to const
|
MATCHconst, // match with conversion to const
|
||||||
#endif
|
|
||||||
MATCHexact // exact match
|
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__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
__attribute__((noreturn))
|
__attribute__((noreturn))
|
||||||
|
#elif _MSC_VER
|
||||||
|
__declspec(noreturn)
|
||||||
#endif
|
#endif
|
||||||
void fatal();
|
void fatal();
|
||||||
|
|
||||||
@@ -538,7 +539,7 @@ void halt();
|
|||||||
#if !IN_LLVM
|
#if !IN_LLVM
|
||||||
class Dsymbol;
|
class Dsymbol;
|
||||||
class Library;
|
class Library;
|
||||||
class File;
|
struct File;
|
||||||
void obj_start(char *srcfile);
|
void obj_start(char *srcfile);
|
||||||
void obj_end(Library *library, File *objfile);
|
void obj_end(Library *library, File *objfile);
|
||||||
void obj_append(Dsymbol *s);
|
void obj_append(Dsymbol *s);
|
||||||
|
|||||||
+56
-33
@@ -44,7 +44,7 @@ void Module::init()
|
|||||||
modules = new DsymbolTable();
|
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)
|
: Package(ident)
|
||||||
{
|
{
|
||||||
const char *srcfilename;
|
const char *srcfilename;
|
||||||
@@ -90,7 +90,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
|||||||
|
|
||||||
macrotable = NULL;
|
macrotable = NULL;
|
||||||
escapetable = NULL;
|
escapetable = NULL;
|
||||||
safe = FALSE;
|
safe = false;
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
doppelganger = 0;
|
doppelganger = 0;
|
||||||
cov = NULL;
|
cov = NULL;
|
||||||
@@ -101,7 +101,30 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
|||||||
namelen = 0;
|
namelen = 0;
|
||||||
|
|
||||||
srcfilename = FileName::defaultExt(filename, global.mars_ext);
|
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, global.hdr_ext) &&
|
||||||
!FileName::equalsExt(srcfilename, "dd"))
|
!FileName::equalsExt(srcfilename, "dd"))
|
||||||
{
|
{
|
||||||
@@ -303,7 +326,7 @@ bool Module::read(Loc loc)
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < global.path->dim; i++)
|
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);
|
fprintf(stderr, "import path[%llu] = %s\n", (ulonglong)i, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,7 +422,7 @@ void Module::parse()
|
|||||||
char *srcname = srcfile->name->toChars();
|
char *srcname = srcfile->name->toChars();
|
||||||
//printf("Module::parse(srcname = '%s')\n", srcname);
|
//printf("Module::parse(srcname = '%s')\n", srcname);
|
||||||
|
|
||||||
utf8_t *buf = srcfile->buffer;
|
utf8_t *buf = (utf8_t *)srcfile->buffer;
|
||||||
size_t buflen = srcfile->len;
|
size_t buflen = srcfile->len;
|
||||||
|
|
||||||
if (buflen >= 2)
|
if (buflen >= 2)
|
||||||
@@ -578,28 +601,30 @@ void Module::parse()
|
|||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
Parser p(this, buf, buflen, gen_docs);
|
Parser p(this, buf, buflen, gen_docs);
|
||||||
#else
|
#else
|
||||||
Parser p(this, buf, buflen, docfile != NULL);
|
Parser p(this, buf, buflen, docfile != NULL);
|
||||||
#endif
|
#endif
|
||||||
p.nextToken();
|
p.nextToken();
|
||||||
members = p.parseModule();
|
members = p.parseModule();
|
||||||
|
md = p.md;
|
||||||
|
numlines = p.scanloc.linnum;
|
||||||
|
}
|
||||||
|
|
||||||
if (srcfile->ref == 0)
|
if (srcfile->ref == 0)
|
||||||
::free(srcfile->buffer);
|
::free(srcfile->buffer);
|
||||||
srcfile->buffer = NULL;
|
srcfile->buffer = NULL;
|
||||||
srcfile->len = 0;
|
srcfile->len = 0;
|
||||||
|
|
||||||
md = p.md;
|
|
||||||
numlines = p.scanloc.linnum;
|
|
||||||
|
|
||||||
/* The symbol table into which the module is to be inserted.
|
/* The symbol table into which the module is to be inserted.
|
||||||
*/
|
*/
|
||||||
DsymbolTable *dst;
|
DsymbolTable *dst;
|
||||||
|
|
||||||
if (md)
|
if (md)
|
||||||
{ /* A ModuleDeclaration, md, was provided.
|
{
|
||||||
|
/* A ModuleDeclaration, md, was provided.
|
||||||
* The ModuleDeclaration sets the packages this module appears in, and
|
* The ModuleDeclaration sets the packages this module appears in, and
|
||||||
* the name of this module.
|
* the name of this module.
|
||||||
*/
|
*/
|
||||||
@@ -608,17 +633,17 @@ void Module::parse()
|
|||||||
Package *ppack = NULL;
|
Package *ppack = NULL;
|
||||||
dst = Package::resolve(md->packages, &this->parent, &ppack);
|
dst = Package::resolve(md->packages, &this->parent, &ppack);
|
||||||
assert(dst);
|
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",
|
::error(md->loc, "package name '%s' conflicts with usage as a module name in file %s",
|
||||||
ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars());
|
ppack->toPrettyChars(), m->srcfile->toChars());
|
||||||
dst = modules;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
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.
|
* There are no packages.
|
||||||
*/
|
*/
|
||||||
dst = modules; // and so this module goes into global module symbol table
|
dst = modules; // and so this module goes into global module symbol table
|
||||||
@@ -665,8 +690,7 @@ void Module::parse()
|
|||||||
*/
|
*/
|
||||||
Dsymbol *prev = dst->lookup(ident);
|
Dsymbol *prev = dst->lookup(ident);
|
||||||
assert(prev);
|
assert(prev);
|
||||||
Module *mprev = prev->isModule();
|
if (Module *mprev = prev->isModule())
|
||||||
if (mprev)
|
|
||||||
{
|
{
|
||||||
if (strcmp(srcname, mprev->srcfile->toChars()) == 0)
|
if (strcmp(srcname, mprev->srcfile->toChars()) == 0)
|
||||||
error(loc, "from file %s must be imported as module '%s'",
|
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",
|
error(loc, "from file %s conflicts with another module %s from file %s",
|
||||||
srcname, mprev->toChars(), mprev->srcfile->toChars());
|
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 (pkg->isPkgMod == PKGunknown && isPackageMod)
|
||||||
{
|
{
|
||||||
/* If the previous inserted Package is not yet determined as package.d,
|
/* 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",
|
error(pkg->loc, "from file %s conflicts with package name %s",
|
||||||
srcname, pkg->toChars());
|
srcname, pkg->toChars());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
assert(global.errors);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1071,7 +1095,7 @@ void Module::runDeferredSemantic3()
|
|||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
* Recursively look at every module this module imports,
|
* 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.
|
* 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++)
|
for (size_t i = 0; i < aimports.dim; i++)
|
||||||
{ Module *mi = aimports[i];
|
{ Module *mi = aimports[i];
|
||||||
if (mi == m)
|
if (mi == m)
|
||||||
return TRUE;
|
return true;
|
||||||
if (!mi->insearch)
|
if (!mi->insearch)
|
||||||
{
|
{
|
||||||
mi->insearch = 1;
|
mi->insearch = 1;
|
||||||
@@ -1096,7 +1120,7 @@ int Module::imports(Module *m)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
@@ -1191,8 +1215,8 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
|
|||||||
if (packages)
|
if (packages)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < packages->dim; i++)
|
for (size_t i = 0; i < packages->dim; i++)
|
||||||
{ Identifier *pid = (*packages)[i];
|
{
|
||||||
|
Identifier *pid = (*packages)[i];
|
||||||
Package *pkg;
|
Package *pkg;
|
||||||
Dsymbol *p = dst->lookup(pid);
|
Dsymbol *p = dst->lookup(pid);
|
||||||
if (!p)
|
if (!p)
|
||||||
@@ -1219,14 +1243,13 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
|
|||||||
dst = pkg->symtab;
|
dst = pkg->symtab;
|
||||||
if (ppkg && !*ppkg)
|
if (ppkg && !*ppkg)
|
||||||
*ppkg = pkg;
|
*ppkg = pkg;
|
||||||
#if 0
|
|
||||||
if (pkg->isModule())
|
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)
|
if (ppkg)
|
||||||
*ppkg = (Package *)p;
|
*ppkg = (Package *)p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pparent)
|
if (pparent)
|
||||||
|
|||||||
+6
-5
@@ -81,6 +81,7 @@ public:
|
|||||||
|
|
||||||
static AggregateDeclaration *moduleinfo;
|
static AggregateDeclaration *moduleinfo;
|
||||||
|
|
||||||
|
|
||||||
const char *arg; // original argument name
|
const char *arg; // original argument name
|
||||||
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
|
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
|
||||||
File *srcfile; // input source file
|
File *srcfile; // input source file
|
||||||
@@ -88,7 +89,6 @@ public:
|
|||||||
File *hdrfile; // 'header' file
|
File *hdrfile; // 'header' file
|
||||||
File *symfile; // output symbol file
|
File *symfile; // output symbol file
|
||||||
File *docfile; // output documentation file
|
File *docfile; // output documentation file
|
||||||
|
|
||||||
unsigned errors; // if any errors in file
|
unsigned errors; // if any errors in file
|
||||||
unsigned numlines; // number of lines in source file
|
unsigned numlines; // number of lines in source file
|
||||||
int isDocFile; // if it is a documentation input file, not D source
|
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 nameoffset; // offset of module name from start of ModuleInfo
|
||||||
size_t namelen; // length of module name in characters
|
size_t namelen; // length of module name in characters
|
||||||
|
|
||||||
int doDocComment; // enable generating doc comments for this module
|
bool doDocComment; // enable generating doc comments for this module
|
||||||
int doHdrGen; // enable generating header file 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();
|
~Module();
|
||||||
|
|
||||||
static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
|
static Module *load(Loc loc, Identifiers *packages, Identifier *ident);
|
||||||
@@ -199,12 +199,13 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
void genmoduleinfo();
|
void genmoduleinfo();
|
||||||
|
|
||||||
|
Module *isModule() { return this; }
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
// LDC
|
// LDC
|
||||||
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
|
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
|
||||||
void buildTargetFiles(bool singleObj);
|
void buildTargetFiles(bool singleObj);
|
||||||
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
File* buildFilePath(const char* forcename, const char* path, const char* ext);
|
||||||
Module *isModule() { return this; }
|
|
||||||
llvm::GlobalVariable* moduleInfoSymbol();
|
llvm::GlobalVariable* moduleInfoSymbol();
|
||||||
|
|
||||||
bool llvmForceLogging;
|
bool llvmForceLogging;
|
||||||
|
|||||||
+303
-238
File diff suppressed because it is too large
Load Diff
+35
-40
@@ -116,8 +116,6 @@ enum ENUMTY
|
|||||||
};
|
};
|
||||||
typedef unsigned char TY; // ENUMTY
|
typedef unsigned char TY; // ENUMTY
|
||||||
|
|
||||||
#define Tascii Tchar
|
|
||||||
|
|
||||||
extern int Tsize_t;
|
extern int Tsize_t;
|
||||||
extern int Tptrdiff_t;
|
extern int Tptrdiff_t;
|
||||||
|
|
||||||
@@ -267,13 +265,13 @@ public:
|
|||||||
#if CPP_MANGLE
|
#if CPP_MANGLE
|
||||||
virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||||
#endif
|
#endif
|
||||||
virtual int isintegral();
|
virtual bool isintegral();
|
||||||
virtual int isfloating(); // real, imaginary, or complex
|
virtual bool isfloating(); // real, imaginary, or complex
|
||||||
virtual int isreal();
|
virtual bool isreal();
|
||||||
virtual int isimaginary();
|
virtual bool isimaginary();
|
||||||
virtual int iscomplex();
|
virtual bool iscomplex();
|
||||||
virtual int isscalar();
|
virtual bool isscalar();
|
||||||
virtual int isunsigned();
|
virtual bool isunsigned();
|
||||||
virtual int isscope();
|
virtual int isscope();
|
||||||
virtual int isString();
|
virtual int isString();
|
||||||
virtual int isAssignable();
|
virtual int isAssignable();
|
||||||
@@ -432,13 +430,13 @@ public:
|
|||||||
#if CPP_MANGLE
|
#if CPP_MANGLE
|
||||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||||
#endif
|
#endif
|
||||||
int isintegral();
|
bool isintegral();
|
||||||
int isfloating();
|
bool isfloating();
|
||||||
int isreal();
|
bool isreal();
|
||||||
int isimaginary();
|
bool isimaginary();
|
||||||
int iscomplex();
|
bool iscomplex();
|
||||||
int isscalar();
|
bool isscalar();
|
||||||
int isunsigned();
|
bool isunsigned();
|
||||||
MATCH implicitConvTo(Type *to);
|
MATCH implicitConvTo(Type *to);
|
||||||
Expression *defaultInit(Loc loc);
|
Expression *defaultInit(Loc loc);
|
||||||
int isZeroInit(Loc loc);
|
int isZeroInit(Loc loc);
|
||||||
@@ -471,10 +469,10 @@ public:
|
|||||||
#if CPP_MANGLE
|
#if CPP_MANGLE
|
||||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||||
#endif
|
#endif
|
||||||
int isintegral();
|
bool isintegral();
|
||||||
int isfloating();
|
bool isfloating();
|
||||||
int isscalar();
|
bool isscalar();
|
||||||
int isunsigned();
|
bool isunsigned();
|
||||||
int checkBoolean();
|
int checkBoolean();
|
||||||
MATCH implicitConvTo(Type *to);
|
MATCH implicitConvTo(Type *to);
|
||||||
Expression *defaultInit(Loc loc);
|
Expression *defaultInit(Loc loc);
|
||||||
@@ -633,7 +631,7 @@ public:
|
|||||||
void toJson(JsonOut *json);
|
void toJson(JsonOut *json);
|
||||||
MATCH implicitConvTo(Type *to);
|
MATCH implicitConvTo(Type *to);
|
||||||
MATCH constConv(Type *to);
|
MATCH constConv(Type *to);
|
||||||
int isscalar();
|
bool isscalar();
|
||||||
Expression *defaultInit(Loc loc);
|
Expression *defaultInit(Loc loc);
|
||||||
int isZeroInit(Loc loc);
|
int isZeroInit(Loc loc);
|
||||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||||
@@ -953,13 +951,13 @@ public:
|
|||||||
void toJson(JsonOut *json);
|
void toJson(JsonOut *json);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
|
||||||
Expression *getProperty(Loc loc, Identifier *ident, int flag);
|
Expression *getProperty(Loc loc, Identifier *ident, int flag);
|
||||||
int isintegral();
|
bool isintegral();
|
||||||
int isfloating();
|
bool isfloating();
|
||||||
int isreal();
|
bool isreal();
|
||||||
int isimaginary();
|
bool isimaginary();
|
||||||
int iscomplex();
|
bool iscomplex();
|
||||||
int isscalar();
|
bool isscalar();
|
||||||
int isunsigned();
|
bool isunsigned();
|
||||||
int checkBoolean();
|
int checkBoolean();
|
||||||
int isString();
|
int isString();
|
||||||
int isAssignable();
|
int isAssignable();
|
||||||
@@ -1003,13 +1001,13 @@ public:
|
|||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
|
||||||
structalign_t alignment();
|
structalign_t alignment();
|
||||||
Expression *getProperty(Loc loc, Identifier *ident, int flag);
|
Expression *getProperty(Loc loc, Identifier *ident, int flag);
|
||||||
int isintegral();
|
bool isintegral();
|
||||||
int isfloating();
|
bool isfloating();
|
||||||
int isreal();
|
bool isreal();
|
||||||
int isimaginary();
|
bool isimaginary();
|
||||||
int iscomplex();
|
bool iscomplex();
|
||||||
int isscalar();
|
bool isscalar();
|
||||||
int isunsigned();
|
bool isunsigned();
|
||||||
int checkBoolean();
|
int checkBoolean();
|
||||||
int isAssignable();
|
int isAssignable();
|
||||||
int needsDestruction();
|
int needsDestruction();
|
||||||
@@ -1131,7 +1129,7 @@ public:
|
|||||||
MATCH implicitConvTo(Type *to);
|
MATCH implicitConvTo(Type *to);
|
||||||
int checkBoolean();
|
int checkBoolean();
|
||||||
|
|
||||||
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
void toJson(JsonOut *json);
|
void toJson(JsonOut *json);
|
||||||
|
|
||||||
d_uns64 size(Loc loc);
|
d_uns64 size(Loc loc);
|
||||||
@@ -1171,16 +1169,13 @@ public:
|
|||||||
static int foreach(Parameters *args, ForeachDg dg, void *ctx, size_t *pn=NULL);
|
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 arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
|
||||||
int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2);
|
int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2);
|
||||||
void MODtoBuffer(OutBuffer *buf, unsigned char mod);
|
void MODtoBuffer(OutBuffer *buf, unsigned char mod);
|
||||||
char *MODtoChars(unsigned char mod);
|
char *MODtoChars(unsigned char mod);
|
||||||
int MODimplicitConv(unsigned char modfrom, unsigned char modto);
|
int MODimplicitConv(unsigned char modfrom, unsigned char modto);
|
||||||
int MODmethodConv(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);
|
void identifierToDocBuffer(Identifier* ident, OutBuffer *buf, HdrGenState *hgs);
|
||||||
|
|
||||||
#endif /* DMD_MTYPE_H */
|
#endif /* DMD_MTYPE_H */
|
||||||
|
|||||||
+9
-40
@@ -13,11 +13,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h> // memset()
|
#include <string.h> // memset()
|
||||||
#if _MSC_VER || IN_LLVM // complex.h breaks LLVM headers.
|
|
||||||
#include <complex>
|
|
||||||
#else
|
|
||||||
#include <complex.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#define integer_t dmd_integer_t
|
#define integer_t dmd_integer_t
|
||||||
@@ -50,7 +45,7 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flag
|
|||||||
|
|
||||||
int Expression::isCommutative()
|
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::postinc
|
||||||
: Id::postdec; }
|
: Id::postdec; }
|
||||||
|
|
||||||
int AddExp::isCommutative() { return TRUE; }
|
int AddExp::isCommutative() { return true; }
|
||||||
Identifier *AddExp::opId() { return Id::add; }
|
Identifier *AddExp::opId() { return Id::add; }
|
||||||
Identifier *AddExp::opId_r() { return Id::add_r; }
|
Identifier *AddExp::opId_r() { return Id::add_r; }
|
||||||
|
|
||||||
Identifier *MinExp::opId() { return Id::sub; }
|
Identifier *MinExp::opId() { return Id::sub; }
|
||||||
Identifier *MinExp::opId_r() { return Id::sub_r; }
|
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() { return Id::mul; }
|
||||||
Identifier *MulExp::opId_r() { return Id::mul_r; }
|
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() { return Id::mod; }
|
||||||
Identifier *ModExp::opId_r() { return Id::mod_r; }
|
Identifier *ModExp::opId_r() { return Id::mod_r; }
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
Identifier *PowExp::opId() { return Id::pow; }
|
Identifier *PowExp::opId() { return Id::pow; }
|
||||||
Identifier *PowExp::opId_r() { return Id::pow_r; }
|
Identifier *PowExp::opId_r() { return Id::pow_r; }
|
||||||
#endif
|
|
||||||
|
|
||||||
Identifier *ShlExp::opId() { return Id::shl; }
|
Identifier *ShlExp::opId() { return Id::shl; }
|
||||||
Identifier *ShlExp::opId_r() { return Id::shl_r; }
|
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() { return Id::ushr; }
|
||||||
Identifier *UshrExp::opId_r() { return Id::ushr_r; }
|
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() { return Id::iand; }
|
||||||
Identifier *AndExp::opId_r() { return Id::iand_r; }
|
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() { return Id::ior; }
|
||||||
Identifier *OrExp::opId_r() { return Id::ior_r; }
|
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() { return Id::ixor; }
|
||||||
Identifier *XorExp::opId_r() { return Id::ixor_r; }
|
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 * CatAssignExp::opId() { return Id::catass; }
|
||||||
Identifier * PowAssignExp::opId() { return Id::powass; }
|
Identifier * PowAssignExp::opId() { return Id::powass; }
|
||||||
|
|
||||||
int EqualExp::isCommutative() { return TRUE; }
|
int EqualExp::isCommutative() { return true; }
|
||||||
Identifier *EqualExp::opId() { return Id::eq; }
|
Identifier *EqualExp::opId() { return Id::eq; }
|
||||||
|
|
||||||
int CmpExp::isCommutative() { return TRUE; }
|
int CmpExp::isCommutative() { return true; }
|
||||||
Identifier *CmpExp::opId() { return Id::cmp; }
|
Identifier *CmpExp::opId() { return Id::cmp; }
|
||||||
|
|
||||||
Identifier *ArrayExp::opId() { return Id::index; }
|
Identifier *ArrayExp::opId() { return Id::index; }
|
||||||
@@ -219,7 +212,6 @@ Expression *UnaExp::op_overload(Scope *sc)
|
|||||||
{
|
{
|
||||||
//printf("UnaExp::op_overload() (%s)\n", toChars());
|
//printf("UnaExp::op_overload() (%s)\n", toChars());
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (e1->op == TOKarray)
|
if (e1->op == TOKarray)
|
||||||
{
|
{
|
||||||
ArrayExp *ae = (ArrayExp *)e1;
|
ArrayExp *ae = (ArrayExp *)e1;
|
||||||
@@ -311,7 +303,6 @@ Expression *UnaExp::op_overload(Scope *sc)
|
|||||||
att1 = NULL;
|
att1 = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
e1 = e1->semantic(sc);
|
e1 = e1->semantic(sc);
|
||||||
e1 = resolveProperties(sc, e1);
|
e1 = resolveProperties(sc, e1);
|
||||||
@@ -345,7 +336,6 @@ Expression *UnaExp::op_overload(Scope *sc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
/* Rewrite as:
|
/* Rewrite as:
|
||||||
* e1.opUnary!("+")();
|
* e1.opUnary!("+")();
|
||||||
*/
|
*/
|
||||||
@@ -373,7 +363,6 @@ Expression *UnaExp::op_overload(Scope *sc)
|
|||||||
ue->e1 = e1;
|
ue->e1 = e1;
|
||||||
return ue->trySemantic(sc);
|
return ue->trySemantic(sc);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -501,7 +490,6 @@ Expression *BinExp::op_overload(Scope *sc)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Objects *tiargs = NULL;
|
Objects *tiargs = NULL;
|
||||||
#if DMDV2
|
|
||||||
if (op == TOKplusplus || op == TOKminusminus)
|
if (op == TOKplusplus || op == TOKminusminus)
|
||||||
{ // Bug4099 fix
|
{ // Bug4099 fix
|
||||||
if (ad1 && search_function(ad1, Id::opUnary))
|
if (ad1 && search_function(ad1, Id::opUnary))
|
||||||
@@ -537,7 +525,6 @@ Expression *BinExp::op_overload(Scope *sc)
|
|||||||
tiargs = opToArg(sc, op);
|
tiargs = opToArg(sc, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s || s_r)
|
if (s || s_r)
|
||||||
{
|
{
|
||||||
@@ -692,7 +679,6 @@ L1:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
// Try alias this on first operand
|
// Try alias this on first operand
|
||||||
if (ad1 && ad1->aliasthis &&
|
if (ad1 && ad1->aliasthis &&
|
||||||
!(op == TOKassign && ad2 && ad1 == ad2)) // See Bugzilla 2943
|
!(op == TOKassign && ad2 && ad1 == ad2)) // See Bugzilla 2943
|
||||||
@@ -731,7 +717,6 @@ L1:
|
|||||||
be->e2 = e2;
|
be->e2 = e2;
|
||||||
return be->trySemantic(sc);
|
return be->trySemantic(sc);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -948,7 +933,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
|||||||
{
|
{
|
||||||
//printf("BinAssignExp::op_overload() (%s)\n", toChars());
|
//printf("BinAssignExp::op_overload() (%s)\n", toChars());
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (e1->op == TOKarray)
|
if (e1->op == TOKarray)
|
||||||
{
|
{
|
||||||
ArrayExp *ae = (ArrayExp *)e1;
|
ArrayExp *ae = (ArrayExp *)e1;
|
||||||
@@ -1045,7 +1029,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
|||||||
att1 = NULL;
|
att1 = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
BinExp::semantic(sc);
|
BinExp::semantic(sc);
|
||||||
e1 = resolveProperties(sc, e1);
|
e1 = resolveProperties(sc, e1);
|
||||||
@@ -1071,7 +1054,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Objects *tiargs = NULL;
|
Objects *tiargs = NULL;
|
||||||
#if DMDV2
|
|
||||||
if (!s)
|
if (!s)
|
||||||
{ /* Try the new D2 scheme, opOpAssign
|
{ /* Try the new D2 scheme, opOpAssign
|
||||||
*/
|
*/
|
||||||
@@ -1091,7 +1073,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
|||||||
tiargs = opToArg(sc, op);
|
tiargs = opToArg(sc, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
@@ -1131,7 +1112,6 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
|||||||
|
|
||||||
L1:
|
L1:
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
// Try alias this on first operand
|
// Try alias this on first operand
|
||||||
if (ad1 && ad1->aliasthis)
|
if (ad1 && ad1->aliasthis)
|
||||||
{
|
{
|
||||||
@@ -1166,7 +1146,6 @@ L1:
|
|||||||
be->e2 = e2;
|
be->e2 = e2;
|
||||||
return be->trySemantic(sc);
|
return be->trySemantic(sc);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1226,10 +1205,8 @@ Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
|
|||||||
int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
|
int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
|
||||||
{
|
{
|
||||||
Identifier *idapply = (op == TOKforeach) ? Id::apply : Id::applyReverse;
|
Identifier *idapply = (op == TOKforeach) ? Id::apply : Id::applyReverse;
|
||||||
#if DMDV2
|
|
||||||
Identifier *idfront = (op == TOKforeach) ? Id::Ffront : Id::Fback;
|
Identifier *idfront = (op == TOKforeach) ? Id::Ffront : Id::Fback;
|
||||||
int sliced = 0;
|
int sliced = 0;
|
||||||
#endif
|
|
||||||
Type *tab;
|
Type *tab;
|
||||||
Type *att = NULL;
|
Type *att = NULL;
|
||||||
Expression *org_aggr = aggr;
|
Expression *org_aggr = aggr;
|
||||||
@@ -1265,7 +1242,6 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
|
|||||||
goto Laggr;
|
goto Laggr;
|
||||||
|
|
||||||
Laggr:
|
Laggr:
|
||||||
#if DMDV2
|
|
||||||
if (!sliced)
|
if (!sliced)
|
||||||
{
|
{
|
||||||
sapply = search_function(ad, idapply);
|
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);
|
aggr = new DotIdExp(aggr->loc, aggr, ad->aliasthis->ident);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
sapply = search_function(ad, idapply);
|
|
||||||
if (sapply)
|
|
||||||
{ // opApply aggregate
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
goto Lerr;
|
goto Lerr;
|
||||||
|
|
||||||
case Tdelegate:
|
case Tdelegate:
|
||||||
@@ -1488,7 +1457,7 @@ static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart,
|
|||||||
struct ParamOpOver
|
struct ParamOpOver
|
||||||
{
|
{
|
||||||
Parameters *arguments;
|
Parameters *arguments;
|
||||||
int mod;
|
unsigned char mod;
|
||||||
MATCH match;
|
MATCH match;
|
||||||
FuncDeclaration *fd_best;
|
FuncDeclaration *fd_best;
|
||||||
FuncDeclaration *fd_ambig;
|
FuncDeclaration *fd_ambig;
|
||||||
|
|||||||
+16
-21
@@ -13,10 +13,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#if __DMC__
|
|
||||||
#include <complex.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
@@ -421,7 +417,7 @@ Expression *PtrExp::optimize(int result, bool keepLvalue)
|
|||||||
Expression *e = expandVar(result, v);
|
Expression *e = expandVar(result, v);
|
||||||
if (e && e->op == TOKstructliteral)
|
if (e && e->op == TOKstructliteral)
|
||||||
{ StructLiteralExp *sle = (StructLiteralExp *)e;
|
{ StructLiteralExp *sle = (StructLiteralExp *)e;
|
||||||
e = sle->getField(type, se->offset);
|
e = sle->getField(type, (unsigned)se->offset);
|
||||||
if (e && e != EXP_CANT_INTERPRET)
|
if (e && e != EXP_CANT_INTERPRET)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -449,7 +445,7 @@ Expression *DotVarExp::optimize(int result, bool keepLvalue)
|
|||||||
VarDeclaration *vf = var->isVarDeclaration();
|
VarDeclaration *vf = var->isVarDeclaration();
|
||||||
if (vf)
|
if (vf)
|
||||||
{
|
{
|
||||||
Expression *e = sle->getField(type, vf->offset);
|
e = sle->getField(type, vf->offset);
|
||||||
if (e && e != EXP_CANT_INTERPRET)
|
if (e && e != EXP_CANT_INTERPRET)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -489,7 +485,6 @@ Expression *NewExp::optimize(int result, bool keepLvalue)
|
|||||||
Expression *CallExp::optimize(int result, bool keepLvalue)
|
Expression *CallExp::optimize(int result, bool keepLvalue)
|
||||||
{
|
{
|
||||||
//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
|
//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
|
||||||
Expression *e = this;
|
|
||||||
|
|
||||||
// Optimize parameters with keeping lvalue-ness
|
// Optimize parameters with keeping lvalue-ness
|
||||||
if (arguments)
|
if (arguments)
|
||||||
@@ -502,9 +497,9 @@ Expression *CallExp::optimize(int result, bool keepLvalue)
|
|||||||
for (size_t i = 0; i < arguments->dim; i++)
|
for (size_t i = 0; i < arguments->dim; i++)
|
||||||
{
|
{
|
||||||
Parameter *p = Parameter::getNth(tf->parameters, 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];
|
Expression *e = (*arguments)[i];
|
||||||
e = e->optimize(WANTvalue, keepLvalue);
|
e = e->optimize(WANTvalue, keep);
|
||||||
(*arguments)[i] = e;
|
(*arguments)[i] = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -513,6 +508,7 @@ Expression *CallExp::optimize(int result, bool keepLvalue)
|
|||||||
if (keepLvalue)
|
if (keepLvalue)
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
|
Expression *e = this;
|
||||||
#if 1
|
#if 1
|
||||||
#else
|
#else
|
||||||
if (e1->op == TOKvar)
|
if (e1->op == TOKvar)
|
||||||
@@ -573,7 +569,10 @@ Expression *CastExp::optimize(int result, bool keepLvalue)
|
|||||||
e1->type->implicitConvTo(type) >= MATCHconst)
|
e1->type->implicitConvTo(type) >= MATCHconst)
|
||||||
{
|
{
|
||||||
if (X) printf(" returning2 %s\n", e1->toChars());
|
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
|
/* The first test here is to prevent infinite loops
|
||||||
@@ -632,10 +631,6 @@ Expression *CastExp::optimize(int result, bool keepLvalue)
|
|||||||
e = this;
|
e = this;
|
||||||
if (X) printf(" returning6 %s\n", e->toChars());
|
if (X) printf(" returning6 %s\n", e->toChars());
|
||||||
return e;
|
return e;
|
||||||
L1: // Returning e1 with changing its type
|
|
||||||
e = (e1old == e1 ? e1->copy() : e1);
|
|
||||||
e->type = type;
|
|
||||||
return e;
|
|
||||||
#undef X
|
#undef X
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1034,7 +1029,7 @@ void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr)
|
|||||||
{
|
{
|
||||||
Type *t = arr->type->toBasetype();
|
Type *t = arr->type->toBasetype();
|
||||||
if (t->ty == Tsarray)
|
if (t->ty == Tsarray)
|
||||||
len = ((TypeSArray *)t)->dim->toInteger();
|
len = (size_t)((TypeSArray *)t)->dim->toInteger();
|
||||||
else
|
else
|
||||||
return; // we don't know the length yet
|
return; // we don't know the length yet
|
||||||
}
|
}
|
||||||
@@ -1100,7 +1095,7 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue)
|
|||||||
if (e1->op == TOKerror)
|
if (e1->op == TOKerror)
|
||||||
return e1;
|
return e1;
|
||||||
e = this;
|
e = this;
|
||||||
if (e1->isBool(FALSE))
|
if (e1->isBool(false))
|
||||||
{
|
{
|
||||||
if (type->toBasetype()->ty == Tvoid)
|
if (type->toBasetype()->ty == Tvoid)
|
||||||
e = e2;
|
e = e2;
|
||||||
@@ -1126,7 +1121,7 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue)
|
|||||||
|
|
||||||
e = new IntegerExp(loc, n1 && n2, type);
|
e = new IntegerExp(loc, n1 && n2, type);
|
||||||
}
|
}
|
||||||
else if (e1->isBool(TRUE))
|
else if (e1->isBool(true))
|
||||||
{
|
{
|
||||||
if (type->toBasetype()->ty == Tvoid)
|
if (type->toBasetype()->ty == Tvoid)
|
||||||
e = e2;
|
e = e2;
|
||||||
@@ -1144,7 +1139,7 @@ Expression *OrOrExp::optimize(int result, bool keepLvalue)
|
|||||||
if (e1->op == TOKerror)
|
if (e1->op == TOKerror)
|
||||||
return e1;
|
return e1;
|
||||||
e = this;
|
e = this;
|
||||||
if (e1->isBool(TRUE))
|
if (e1->isBool(true))
|
||||||
{ // Replace with (e1, 1)
|
{ // Replace with (e1, 1)
|
||||||
e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
|
e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
|
||||||
e->type = type;
|
e->type = type;
|
||||||
@@ -1166,7 +1161,7 @@ Expression *OrOrExp::optimize(int result, bool keepLvalue)
|
|||||||
|
|
||||||
e = new IntegerExp(loc, n1 || n2, type);
|
e = new IntegerExp(loc, n1 || n2, type);
|
||||||
}
|
}
|
||||||
else if (e1->isBool(FALSE))
|
else if (e1->isBool(false))
|
||||||
{
|
{
|
||||||
if (type->toBasetype()->ty == Tvoid)
|
if (type->toBasetype()->ty == Tvoid)
|
||||||
e = e2;
|
e = e2;
|
||||||
@@ -1211,9 +1206,9 @@ Expression *CondExp::optimize(int result, bool keepLvalue)
|
|||||||
{ Expression *e;
|
{ Expression *e;
|
||||||
|
|
||||||
econd = econd->optimize(WANTflags);
|
econd = econd->optimize(WANTflags);
|
||||||
if (econd->isBool(TRUE))
|
if (econd->isBool(true))
|
||||||
e = e1->optimize(result, keepLvalue);
|
e = e1->optimize(result, keepLvalue);
|
||||||
else if (econd->isBool(FALSE))
|
else if (econd->isBool(false))
|
||||||
e = e2->optimize(result, keepLvalue);
|
e = e2->optimize(result, keepLvalue);
|
||||||
else
|
else
|
||||||
{ e1 = e1->optimize(result, keepLvalue);
|
{ e1 = e1->optimize(result, keepLvalue);
|
||||||
|
|||||||
+157
-277
File diff suppressed because it is too large
Load Diff
+7
-10
@@ -69,18 +69,19 @@ public:
|
|||||||
int inBrackets; // inside [] of array index or slice
|
int inBrackets; // inside [] of array index or slice
|
||||||
Loc lookingForElse; // location of lonely if looking for an else
|
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 *parseModule();
|
||||||
Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL);
|
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);
|
Dsymbols *parseBlock(Dsymbol **pLastDecl);
|
||||||
void composeStorageClass(StorageClass stc);
|
void composeStorageClass(StorageClass stc);
|
||||||
StorageClass parseAttribute(Expressions **pexps);
|
StorageClass parseAttribute(Expressions **pexps);
|
||||||
StorageClass parsePostfix();
|
StorageClass parsePostfix();
|
||||||
StorageClass parseTypeCtor();
|
StorageClass parseTypeCtor();
|
||||||
Expression *parseConstraint();
|
Expression *parseConstraint();
|
||||||
TemplateDeclaration *parseTemplateDeclaration(int ismixin);
|
TemplateDeclaration *parseTemplateDeclaration(bool ismixin = false);
|
||||||
TemplateParameters *parseTemplateParameterList(int flag = 0);
|
TemplateParameters *parseTemplateParameterList(int flag = 0);
|
||||||
Dsymbol *parseMixin();
|
Dsymbol *parseMixin();
|
||||||
Objects *parseTemplateArgumentList();
|
Objects *parseTemplateArgumentList();
|
||||||
@@ -112,11 +113,11 @@ public:
|
|||||||
Type *parseBasicType();
|
Type *parseBasicType();
|
||||||
Type *parseBasicType2(Type *t);
|
Type *parseBasicType2(Type *t);
|
||||||
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int* pdisable = NULL);
|
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 parseContracts(FuncDeclaration *f);
|
||||||
void checkDanglingElse(Loc elseloc);
|
void checkDanglingElse(Loc elseloc);
|
||||||
/** endPtr used for documented unittests */
|
/** endPtr used for documented unittests */
|
||||||
Statement *parseStatement(int flags, utf8_t** endPtr = NULL);
|
Statement *parseStatement(int flags, const utf8_t** endPtr = NULL);
|
||||||
Initializer *parseInitializer();
|
Initializer *parseInitializer();
|
||||||
Expression *parseDefaultInitExp();
|
Expression *parseDefaultInitExp();
|
||||||
void check(Loc loc, TOK value);
|
void check(Loc loc, TOK value);
|
||||||
@@ -138,10 +139,6 @@ public:
|
|||||||
Expression *parseMulExp();
|
Expression *parseMulExp();
|
||||||
Expression *parseAddExp();
|
Expression *parseAddExp();
|
||||||
Expression *parseShiftExp();
|
Expression *parseShiftExp();
|
||||||
#if DMDV1
|
|
||||||
Expression *parseRelExp();
|
|
||||||
Expression *parseEqualExp();
|
|
||||||
#endif
|
|
||||||
Expression *parseCmpExp();
|
Expression *parseCmpExp();
|
||||||
Expression *parseAndExp();
|
Expression *parseAndExp();
|
||||||
Expression *parseXorExp();
|
Expression *parseXorExp();
|
||||||
@@ -155,7 +152,7 @@ public:
|
|||||||
|
|
||||||
Expression *parseNewExp(Expression *thisexp);
|
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
|
// Operator precedence - greater values are higher precedence
|
||||||
|
|||||||
@@ -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
@@ -520,6 +520,16 @@ int ld_type(longdouble x)
|
|||||||
|
|
||||||
size_t ld_sprint(char* str, int fmt, 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'
|
// fmt is 'a','A','f' or 'g'
|
||||||
if(fmt != 'a' && fmt != 'A')
|
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 short exp = x.exponent;
|
||||||
unsigned long long mantissa = x.mantissa;
|
unsigned long long mantissa = x.mantissa;
|
||||||
|
|
||||||
switch(ld_type(x))
|
if(ld_type(x) == LD_TYPE_ZERO)
|
||||||
{
|
|
||||||
case LD_TYPE_ZERO:
|
|
||||||
return sprintf(str, "0x0.0L");
|
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;
|
size_t len = 0;
|
||||||
if(x.sign)
|
if(x.sign)
|
||||||
|
|||||||
+1
-1
@@ -763,7 +763,7 @@ int Port::isInfinity(double r)
|
|||||||
|
|
||||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
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
|
return ::fmod(x, y); // hack for now, fix later
|
||||||
#else
|
#else
|
||||||
return ::fmodl(x, y);
|
return ::fmodl(x, y);
|
||||||
|
|||||||
@@ -18,10 +18,6 @@
|
|||||||
|
|
||||||
Mem mem;
|
Mem mem;
|
||||||
|
|
||||||
void Mem::init()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
char *Mem::strdup(const char *s)
|
char *Mem::strdup(const char *s)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
@@ -118,24 +114,6 @@ void Mem::error()
|
|||||||
exit(EXIT_FAILURE);
|
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)
|
#if defined(__has_feature)
|
||||||
|
|||||||
+1
-28
@@ -15,44 +15,17 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <stddef.h> // for size_t
|
#include <stddef.h> // for size_t
|
||||||
|
|
||||||
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
|
|
||||||
|
|
||||||
struct GC; // thread specific allocator
|
|
||||||
|
|
||||||
struct Mem
|
struct Mem
|
||||||
{
|
{
|
||||||
GC *gc; // pointer to our thread specific allocator
|
Mem() { }
|
||||||
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);
|
|
||||||
|
|
||||||
char *strdup(const char *s);
|
char *strdup(const char *s);
|
||||||
void *malloc(size_t size);
|
void *malloc(size_t size);
|
||||||
void *malloc_uncollectable(size_t size);
|
|
||||||
void *calloc(size_t size, size_t n);
|
void *calloc(size_t size, size_t n);
|
||||||
void *realloc(void *p, size_t size);
|
void *realloc(void *p, size_t size);
|
||||||
void free(void *p);
|
void free(void *p);
|
||||||
void free_uncollectable(void *p);
|
|
||||||
void *mallocdup(void *o, size_t size);
|
void *mallocdup(void *o, size_t size);
|
||||||
void error();
|
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;
|
extern Mem mem;
|
||||||
|
|||||||
+9
-254
@@ -103,11 +103,6 @@ bool RootObject::equals(RootObject *o)
|
|||||||
return o == this;
|
return o == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_t RootObject::hashCode()
|
|
||||||
{
|
|
||||||
return (hash_t) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RootObject::compare(RootObject *obj)
|
int RootObject::compare(RootObject *obj)
|
||||||
{
|
{
|
||||||
return this - obj;
|
return this - obj;
|
||||||
@@ -133,104 +128,10 @@ void RootObject::toBuffer(OutBuffer *b)
|
|||||||
b->writestring("Object");
|
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::FileName(const char *str)
|
FileName::FileName(const char *str)
|
||||||
: String(str)
|
: str(mem.strdup(str))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,51 +240,6 @@ Strings *FileName::splitPath(const char *path)
|
|||||||
return array;
|
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)
|
int FileName::compare(RootObject *obj)
|
||||||
{
|
{
|
||||||
return compare(str, ((FileName *)obj)->str);
|
return compare(str, ((FileName *)obj)->str);
|
||||||
@@ -941,6 +797,11 @@ void FileName::free(const char *str)
|
|||||||
mem.free((void *)str);
|
mem.free((void *)str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *FileName::toChars()
|
||||||
|
{
|
||||||
|
return (char *)str; // toChars() should really be const
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************** File ********************************/
|
/****************************** File ********************************/
|
||||||
|
|
||||||
@@ -969,7 +830,7 @@ File::~File()
|
|||||||
if (ref == 0)
|
if (ref == 0)
|
||||||
mem.free(buffer);
|
mem.free(buffer);
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
else if (ref == 2)
|
if (ref == 2)
|
||||||
UnmapViewOfFile(buffer);
|
UnmapViewOfFile(buffer);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -977,13 +838,6 @@ File::~File()
|
|||||||
mem.free(touchtime);
|
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;
|
char *fn;
|
||||||
File *f;
|
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);
|
memcpy(fn, c, name - c);
|
||||||
strcpy(fn + (name - c), fileinfo.cFileName);
|
strcpy(fn + (name - c), &fileinfo.cFileName[0]);
|
||||||
f = new File(fn);
|
f = new File(fn);
|
||||||
f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
|
f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA));
|
||||||
memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
|
memcpy(f->touchtime, &fileinfo, sizeof(fileinfo));
|
||||||
@@ -1490,11 +1344,6 @@ char *OutBuffer::extractData()
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutBuffer::mark()
|
|
||||||
{
|
|
||||||
mem.mark(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OutBuffer::reserve(size_t nbytes)
|
void OutBuffer::reserve(size_t nbytes)
|
||||||
{
|
{
|
||||||
//printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
|
//printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
|
||||||
@@ -1861,97 +1710,3 @@ char *OutBuffer::toChars()
|
|||||||
writeByte(0);
|
writeByte(0);
|
||||||
return (char *)data;
|
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
@@ -31,8 +31,8 @@ struct OutBuffer;
|
|||||||
|
|
||||||
// Can't include arraytypes.h here, need to declare these directly.
|
// Can't include arraytypes.h here, need to declare these directly.
|
||||||
template <typename TYPE> struct Array;
|
template <typename TYPE> struct Array;
|
||||||
typedef Array<class File> Files;
|
typedef Array<struct File> Files;
|
||||||
typedef Array<char> Strings;
|
typedef Array<const char> Strings;
|
||||||
|
|
||||||
|
|
||||||
class RootObject
|
class RootObject
|
||||||
@@ -43,11 +43,6 @@ public:
|
|||||||
|
|
||||||
virtual bool equals(RootObject *o);
|
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.
|
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
||||||
* Useful for sorting Objects.
|
* Useful for sorting Objects.
|
||||||
@@ -67,38 +62,13 @@ public:
|
|||||||
* defined by the library user. For Object, the return value is 0.
|
* defined by the library user. For Object, the return value is 0.
|
||||||
*/
|
*/
|
||||||
virtual int dyncast();
|
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
|
struct FileName
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
const char *str;
|
||||||
FileName(const char *str);
|
FileName(const char *str);
|
||||||
hash_t hashCode();
|
|
||||||
bool equals(RootObject *obj);
|
bool equals(RootObject *obj);
|
||||||
static int equals(const char *name1, const char *name2);
|
static int equals(const char *name1, const char *name2);
|
||||||
int compare(RootObject *obj);
|
int compare(RootObject *obj);
|
||||||
@@ -129,9 +99,10 @@ public:
|
|||||||
static const char *canonicalName(const char *name);
|
static const char *canonicalName(const char *name);
|
||||||
|
|
||||||
static void free(const char *str);
|
static void free(const char *str);
|
||||||
|
char *toChars();
|
||||||
};
|
};
|
||||||
|
|
||||||
class File : public RootObject
|
struct File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int ref; // != 0 if this is a reference to someone else's buffer
|
int ref; // != 0 if this is a reference to someone else's buffer
|
||||||
@@ -145,8 +116,6 @@ public:
|
|||||||
File(const FileName *);
|
File(const FileName *);
|
||||||
~File();
|
~File();
|
||||||
|
|
||||||
void mark();
|
|
||||||
|
|
||||||
char *toChars();
|
char *toChars();
|
||||||
|
|
||||||
/* Read file, return !=0 if error
|
/* Read file, return !=0 if error
|
||||||
@@ -250,7 +219,6 @@ struct OutBuffer
|
|||||||
OutBuffer();
|
OutBuffer();
|
||||||
~OutBuffer();
|
~OutBuffer();
|
||||||
char *extractData();
|
char *extractData();
|
||||||
void mark();
|
|
||||||
|
|
||||||
void reserve(size_t nbytes);
|
void reserve(size_t nbytes);
|
||||||
void setsize(size_t size);
|
void setsize(size_t size);
|
||||||
@@ -308,13 +276,6 @@ struct Array
|
|||||||
mem.free(data);
|
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 *toChars()
|
||||||
{
|
{
|
||||||
char **buf = (char **)malloc(dim * sizeof(char *));
|
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
|
#endif
|
||||||
|
|||||||
+2
-1
@@ -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)
|
void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset)
|
||||||
{
|
{
|
||||||
size_t seedlen = strlen(seed);
|
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);
|
{ void *p = spellerX(seed, seedlen, fp, fparg, charset, distance);
|
||||||
if (p)
|
if (p)
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
+2
-6
@@ -36,7 +36,7 @@ bool Statement::apply(sapply_fp_t fp, void *param)
|
|||||||
/******************************
|
/******************************
|
||||||
* Perform apply() on an t if not null
|
* 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);
|
(*fp)(this, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
bool ForeachRangeStatement::apply(sapply_fp_t fp, void *param)
|
bool ForeachRangeStatement::apply(sapply_fp_t fp, void *param)
|
||||||
{
|
{
|
||||||
return scondApply(body, fp, param) ||
|
return scondApply(body, fp, param) ||
|
||||||
(*fp)(this, param);
|
(*fp)(this, param);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool IfStatement::apply(sapply_fp_t fp, void *param)
|
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);
|
(*fp)(this, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
bool CaseRangeStatement::apply(sapply_fp_t fp, void *param)
|
bool CaseRangeStatement::apply(sapply_fp_t fp, void *param)
|
||||||
{
|
{
|
||||||
return scondApply(statement, fp, param) ||
|
return scondApply(statement, fp, param) ||
|
||||||
(*fp)(this, param);
|
(*fp)(this, param);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool DefaultStatement::apply(sapply_fp_t fp, void *param)
|
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++)
|
for (size_t i = 0; i < catches->dim; i++)
|
||||||
{ Catch *c = (*catches)[i];
|
{ Catch *c = (*catches)[i];
|
||||||
|
|
||||||
bool r = scondApply(c->handler, fp, param);
|
r = scondApply(c->handler, fp, param);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-11
@@ -57,8 +57,12 @@ Scope::Scope()
|
|||||||
this->enclosing = NULL;
|
this->enclosing = NULL;
|
||||||
this->parent = NULL;
|
this->parent = NULL;
|
||||||
this->sw = NULL;
|
this->sw = NULL;
|
||||||
|
#if IN_LLVM
|
||||||
this->enclosingFinally = NULL;
|
this->enclosingFinally = NULL;
|
||||||
this->enclosingScopeExit = NULL;
|
this->enclosingScopeExit = NULL;
|
||||||
|
#else
|
||||||
|
this->tf = NULL;
|
||||||
|
#endif
|
||||||
this->tinst = NULL;
|
this->tinst = NULL;
|
||||||
this->sbreak = NULL;
|
this->sbreak = NULL;
|
||||||
this->scontinue = NULL;
|
this->scontinue = NULL;
|
||||||
@@ -78,6 +82,7 @@ Scope::Scope()
|
|||||||
this->noctor = 0;
|
this->noctor = 0;
|
||||||
this->intypeof = 0;
|
this->intypeof = 0;
|
||||||
this->speculative = 0;
|
this->speculative = 0;
|
||||||
|
this->lastVar = NULL;
|
||||||
this->callSuper = 0;
|
this->callSuper = 0;
|
||||||
this->fieldinit = NULL;
|
this->fieldinit = NULL;
|
||||||
this->fieldinit_dim = 0;
|
this->fieldinit_dim = 0;
|
||||||
@@ -99,8 +104,12 @@ Scope::Scope(Scope *enclosing)
|
|||||||
this->scopesym = NULL;
|
this->scopesym = NULL;
|
||||||
this->sd = NULL;
|
this->sd = NULL;
|
||||||
this->sw = enclosing->sw;
|
this->sw = enclosing->sw;
|
||||||
|
#if IN_LLVM
|
||||||
this->enclosingFinally = enclosing->enclosingFinally;
|
this->enclosingFinally = enclosing->enclosingFinally;
|
||||||
this->enclosingScopeExit = enclosing->enclosingScopeExit;
|
this->enclosingScopeExit = enclosing->enclosingScopeExit;
|
||||||
|
#else
|
||||||
|
this->tf = enclosing->tf;
|
||||||
|
#endif
|
||||||
this->tinst = enclosing->tinst;
|
this->tinst = enclosing->tinst;
|
||||||
this->sbreak = enclosing->sbreak;
|
this->sbreak = enclosing->sbreak;
|
||||||
this->scontinue = enclosing->scontinue;
|
this->scontinue = enclosing->scontinue;
|
||||||
@@ -129,10 +138,11 @@ Scope::Scope(Scope *enclosing)
|
|||||||
this->noctor = enclosing->noctor;
|
this->noctor = enclosing->noctor;
|
||||||
this->intypeof = enclosing->intypeof;
|
this->intypeof = enclosing->intypeof;
|
||||||
this->speculative = enclosing->speculative;
|
this->speculative = enclosing->speculative;
|
||||||
|
this->lastVar = enclosing->lastVar;
|
||||||
this->callSuper = enclosing->callSuper;
|
this->callSuper = enclosing->callSuper;
|
||||||
this->fieldinit = enclosing->saveFieldInit();
|
this->fieldinit = enclosing->saveFieldInit();
|
||||||
this->fieldinit_dim = enclosing->fieldinit_dim;
|
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->lastdc = NULL;
|
||||||
this->lastoffset = 0;
|
this->lastoffset = 0;
|
||||||
this->docbuf = enclosing->docbuf;
|
this->docbuf = enclosing->docbuf;
|
||||||
@@ -191,7 +201,7 @@ Scope *Scope::pop()
|
|||||||
size_t dim = fieldinit_dim;
|
size_t dim = fieldinit_dim;
|
||||||
for (size_t i = 0; i < dim; i++)
|
for (size_t i = 0; i < dim; i++)
|
||||||
enclosing->fieldinit[i] |= fieldinit[i];
|
enclosing->fieldinit[i] |= fieldinit[i];
|
||||||
delete[] fieldinit;
|
mem.free(fieldinit);
|
||||||
fieldinit = NULL;
|
fieldinit = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -277,14 +287,9 @@ unsigned *Scope::saveFieldInit()
|
|||||||
if (fieldinit) // copy
|
if (fieldinit) // copy
|
||||||
{
|
{
|
||||||
size_t dim = fieldinit_dim;
|
size_t dim = fieldinit_dim;
|
||||||
fi = new unsigned[dim];
|
fi = (unsigned *)mem.malloc(sizeof(unsigned) * dim);
|
||||||
#if IN_LLVM // ASan
|
|
||||||
memcpy(fi, fieldinit, sizeof(*fi) * dim);
|
|
||||||
#else
|
|
||||||
fi[0] = dim;
|
|
||||||
for (size_t i = 0; i < dim; i++)
|
for (size_t i = 0; i < dim; i++)
|
||||||
fi[i] = fieldinit[i];
|
fi[i] = fieldinit[i];
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return fi;
|
return fi;
|
||||||
}
|
}
|
||||||
@@ -455,9 +460,24 @@ Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dsymbol *Scope::insert(Dsymbol *s)
|
Dsymbol *Scope::insert(Dsymbol *s)
|
||||||
{ Scope *sc;
|
{
|
||||||
|
if (VarDeclaration *vd = s->isVarDeclaration())
|
||||||
for (sc = this; sc; sc = sc->enclosing)
|
{
|
||||||
|
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);
|
//printf("\tsc = %p\n", sc);
|
||||||
if (sc->scopesym)
|
if (sc->scopesym)
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ enum PROT;
|
|||||||
|
|
||||||
#define SCOPEctfe 0x0080 // inside a ctfe-only expression
|
#define SCOPEctfe 0x0080 // inside a ctfe-only expression
|
||||||
#define SCOPEnoaccesscheck 0x0100 // don't do access checks
|
#define SCOPEnoaccesscheck 0x0100 // don't do access checks
|
||||||
|
#define SCOPEcompile 0x0200 // inside __traits(compile)
|
||||||
|
|
||||||
struct Scope
|
struct Scope
|
||||||
{
|
{
|
||||||
@@ -95,6 +96,7 @@ struct Scope
|
|||||||
int noctor; // set if constructor calls aren't allowed
|
int noctor; // set if constructor calls aren't allowed
|
||||||
int intypeof; // in typeof(exp)
|
int intypeof; // in typeof(exp)
|
||||||
bool speculative; // in __traits(compiles) or 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 callSuper; // primitive flow analysis for constructors
|
||||||
unsigned *fieldinit;
|
unsigned *fieldinit;
|
||||||
|
|||||||
+5
-5
@@ -31,7 +31,7 @@ int lambdaHasSideEffect(Expression *e, void *param);
|
|||||||
|
|
||||||
bool Expression::hasSideEffect()
|
bool Expression::hasSideEffect()
|
||||||
{
|
{
|
||||||
bool has = FALSE;
|
bool has = false;
|
||||||
apply(&lambdaHasSideEffect, &has);
|
apply(&lambdaHasSideEffect, &has);
|
||||||
return has;
|
return has;
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
|
|||||||
case TOKdelete:
|
case TOKdelete:
|
||||||
case TOKnew:
|
case TOKnew:
|
||||||
case TOKnewanonclass:
|
case TOKnewanonclass:
|
||||||
*phas = TRUE;
|
*phas = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKcall:
|
case TOKcall:
|
||||||
@@ -89,7 +89,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*phas = TRUE;
|
*phas = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
|
|||||||
* cast(classtype)func() // because it may throw
|
* cast(classtype)func() // because it may throw
|
||||||
*/
|
*/
|
||||||
if (ce->to->ty == Tclass && ce->e1->op == TOKcall && ce->e1->type->ty == Tclass)
|
if (ce->to->ty == Tclass && ce->e1->op == TOKcall && ce->e1->type->ty == Tclass)
|
||||||
*phas = TRUE;
|
*phas = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ int lambdaHasSideEffect(Expression *e, void *param)
|
|||||||
*/
|
*/
|
||||||
void Expression::discardValue()
|
void Expression::discardValue()
|
||||||
{
|
{
|
||||||
bool has = FALSE;
|
bool has = false;
|
||||||
lambdaHasSideEffect(this, &has);
|
lambdaHasSideEffect(this, &has);
|
||||||
if (!has)
|
if (!has)
|
||||||
{
|
{
|
||||||
|
|||||||
+275
-229
File diff suppressed because it is too large
Load Diff
+9
-8
@@ -326,6 +326,7 @@ public:
|
|||||||
Statement *syntaxCopy();
|
Statement *syntaxCopy();
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
ScopeStatement *isScopeStatement() { return this; }
|
ScopeStatement *isScopeStatement() { return this; }
|
||||||
|
ReturnStatement *isReturnStatement();
|
||||||
Statement *semantic(Scope *sc);
|
Statement *semantic(Scope *sc);
|
||||||
bool hasBreak();
|
bool hasBreak();
|
||||||
bool hasContinue();
|
bool hasContinue();
|
||||||
@@ -434,7 +435,7 @@ public:
|
|||||||
FuncDeclaration *func; // function we're lexically in
|
FuncDeclaration *func; // function we're lexically in
|
||||||
|
|
||||||
Statements *cases; // put breaks, continues, gotos and returns here
|
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);
|
ForeachStatement(Loc loc, TOK op, Parameters *arguments, Expression *aggr, Statement *body);
|
||||||
Statement *syntaxCopy();
|
Statement *syntaxCopy();
|
||||||
@@ -455,7 +456,6 @@ public:
|
|||||||
void toIR(IRState *irs);
|
void toIR(IRState *irs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class ForeachRangeStatement : public Statement
|
class ForeachRangeStatement : public Statement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -483,7 +483,6 @@ public:
|
|||||||
|
|
||||||
void toIR(IRState *irs);
|
void toIR(IRState *irs);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class IfStatement : public Statement
|
class IfStatement : public Statement
|
||||||
{
|
{
|
||||||
@@ -631,7 +630,6 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
|
|
||||||
class CaseRangeStatement : public Statement
|
class CaseRangeStatement : public Statement
|
||||||
{
|
{
|
||||||
@@ -647,7 +645,6 @@ public:
|
|||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class DefaultStatement : public Statement
|
class DefaultStatement : public Statement
|
||||||
{
|
{
|
||||||
@@ -961,16 +958,19 @@ class GotoStatement : public Statement
|
|||||||
public:
|
public:
|
||||||
Identifier *ident;
|
Identifier *ident;
|
||||||
LabelDsymbol *label;
|
LabelDsymbol *label;
|
||||||
#if !IN_LLVM
|
#if IN_LLVM
|
||||||
TryFinallyStatement *tf;
|
|
||||||
#else
|
|
||||||
TryFinallyStatement *enclosingFinally;
|
TryFinallyStatement *enclosingFinally;
|
||||||
Statement* enclosingScopeExit;
|
Statement* enclosingScopeExit;
|
||||||
|
#else
|
||||||
|
TryFinallyStatement *tf;
|
||||||
#endif
|
#endif
|
||||||
|
VarDeclaration *lastVar;
|
||||||
|
FuncDeclaration *fd;
|
||||||
|
|
||||||
GotoStatement(Loc loc, Identifier *ident);
|
GotoStatement(Loc loc, Identifier *ident);
|
||||||
Statement *syntaxCopy();
|
Statement *syntaxCopy();
|
||||||
Statement *semantic(Scope *sc);
|
Statement *semantic(Scope *sc);
|
||||||
|
bool checkLabel();
|
||||||
int blockExit(bool mustNotThrow);
|
int blockExit(bool mustNotThrow);
|
||||||
Expression *interpret(InterState *istate);
|
Expression *interpret(InterState *istate);
|
||||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||||
@@ -991,6 +991,7 @@ public:
|
|||||||
Statement* enclosingScopeExit;
|
Statement* enclosingScopeExit;
|
||||||
#endif
|
#endif
|
||||||
Statement *gotoTarget; // interpret
|
Statement *gotoTarget; // interpret
|
||||||
|
VarDeclaration *lastVar;
|
||||||
block *lblock; // back end
|
block *lblock; // back end
|
||||||
|
|
||||||
Blocks *fwdrefs; // forward references to this LabelStatement
|
Blocks *fwdrefs; // forward references to this LabelStatement
|
||||||
|
|||||||
+2
-2
@@ -77,7 +77,7 @@ void StaticAssert::semantic2(Scope *sc)
|
|||||||
{
|
{
|
||||||
errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
|
errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
|
||||||
}
|
}
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
@@ -105,7 +105,7 @@ void StaticAssert::semantic2(Scope *sc)
|
|||||||
if (!global.gag)
|
if (!global.gag)
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
else if (!e->isBool(TRUE))
|
else if (!e->isBool(true))
|
||||||
{
|
{
|
||||||
error("(%s) is not evaluatable at compile time", exp->toChars());
|
error("(%s) is not evaluatable at compile time", exp->toChars());
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-77
@@ -120,12 +120,10 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
|||||||
enclosing = NULL;
|
enclosing = NULL;
|
||||||
vthis = NULL;
|
vthis = NULL;
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
ctor = NULL;
|
ctor = NULL;
|
||||||
defaultCtor = NULL;
|
defaultCtor = NULL;
|
||||||
aliasthis = NULL;
|
aliasthis = NULL;
|
||||||
noDefaultCtor = FALSE;
|
noDefaultCtor = false;
|
||||||
#endif
|
|
||||||
dtor = NULL;
|
dtor = NULL;
|
||||||
getRTInfo = NULL;
|
getRTInfo = NULL;
|
||||||
|
|
||||||
@@ -565,7 +563,6 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
|||||||
: AggregateDeclaration(loc, id)
|
: AggregateDeclaration(loc, id)
|
||||||
{
|
{
|
||||||
zeroInit = 0; // assume false until we do semantic processing
|
zeroInit = 0; // assume false until we do semantic processing
|
||||||
#if DMDV2
|
|
||||||
hasIdentityAssign = 0;
|
hasIdentityAssign = 0;
|
||||||
hasIdentityEquals = 0;
|
hasIdentityEquals = 0;
|
||||||
cpctor = NULL;
|
cpctor = NULL;
|
||||||
@@ -574,7 +571,6 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
|||||||
xeq = NULL;
|
xeq = NULL;
|
||||||
xcmp = NULL;
|
xcmp = NULL;
|
||||||
alignment = 0;
|
alignment = 0;
|
||||||
#endif
|
|
||||||
arg1type = NULL;
|
arg1type = NULL;
|
||||||
arg2type = NULL;
|
arg2type = NULL;
|
||||||
|
|
||||||
@@ -582,16 +578,8 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
|||||||
type = new TypeStruct(this);
|
type = new TypeStruct(this);
|
||||||
|
|
||||||
#if MODULEINFO_IS_STRUCT
|
#if MODULEINFO_IS_STRUCT
|
||||||
#ifdef DMDV2
|
|
||||||
if (id == Id::ModuleInfo && !Module::moduleinfo)
|
if (id == Id::ModuleInfo && !Module::moduleinfo)
|
||||||
Module::moduleinfo = this;
|
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
|
#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);
|
dtor = buildDtor(sc2);
|
||||||
postblit = buildPostBlit(sc2);
|
postblit = buildPostBlit(sc2);
|
||||||
cpctor = buildCpCtor(sc2);
|
cpctor = buildCpCtor(sc2);
|
||||||
@@ -840,7 +765,6 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
/* Defer requesting semantic3 until TypeInfo generation is actually invoked.
|
/* Defer requesting semantic3 until TypeInfo generation is actually invoked.
|
||||||
* See Type::getTypeInfo().
|
* See Type::getTypeInfo().
|
||||||
*/
|
*/
|
||||||
#endif
|
|
||||||
inv = buildInv(sc2);
|
inv = buildInv(sc2);
|
||||||
|
|
||||||
sc2->pop();
|
sc2->pop();
|
||||||
|
|||||||
+250
-130
@@ -454,7 +454,6 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, RootObject *oarg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
RootObject *objectSyntaxCopy(RootObject *o)
|
RootObject *objectSyntaxCopy(RootObject *o)
|
||||||
{
|
{
|
||||||
if (!o)
|
if (!o)
|
||||||
@@ -467,13 +466,12 @@ RootObject *objectSyntaxCopy(RootObject *o)
|
|||||||
return e->syntaxCopy();
|
return e->syntaxCopy();
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* ======================== TemplateDeclaration ============================= */
|
/* ======================== TemplateDeclaration ============================= */
|
||||||
|
|
||||||
TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
|
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)
|
: ScopeDsymbol(id)
|
||||||
{
|
{
|
||||||
#if LOG
|
#if LOG
|
||||||
@@ -501,8 +499,9 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
|
|||||||
this->overroot = NULL;
|
this->overroot = NULL;
|
||||||
this->funcroot = NULL;
|
this->funcroot = NULL;
|
||||||
this->onemember = NULL;
|
this->onemember = NULL;
|
||||||
this->literal = 0;
|
this->literal = literal;
|
||||||
this->ismixin = ismixin;
|
this->ismixin = ismixin;
|
||||||
|
this->isstatic = true;
|
||||||
this->previous = NULL;
|
this->previous = NULL;
|
||||||
this->protection = PROTundefined;
|
this->protection = PROTundefined;
|
||||||
this->numinstances = 0;
|
this->numinstances = 0;
|
||||||
@@ -540,8 +539,7 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
|
|||||||
if (constraint)
|
if (constraint)
|
||||||
e = constraint->syntaxCopy();
|
e = constraint->syntaxCopy();
|
||||||
Dsymbols *d = Dsymbol::arraySyntaxCopy(members);
|
Dsymbols *d = Dsymbol::arraySyntaxCopy(members);
|
||||||
td = new TemplateDeclaration(loc, ident, p, e, d, ismixin);
|
td = new TemplateDeclaration(loc, ident, p, e, d, ismixin, literal);
|
||||||
td->literal = literal;
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
td->intrinsicName = intrinsicName;
|
td->intrinsicName = intrinsicName;
|
||||||
#endif
|
#endif
|
||||||
@@ -568,13 +566,6 @@ void TemplateDeclaration::semantic(Scope *sc)
|
|||||||
Type::rtinfo = this;
|
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)
|
if (/*global.params.useArrayBounds &&*/ sc->module)
|
||||||
{
|
{
|
||||||
// Generate this function as it may be used
|
// Generate this function as it may be used
|
||||||
@@ -591,7 +582,6 @@ void TemplateDeclaration::semantic(Scope *sc)
|
|||||||
//sc->module->toModuleAssert();
|
//sc->module->toModuleAssert();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (sc->module)
|
if (sc->module)
|
||||||
{
|
{
|
||||||
// Generate this function as it may be used
|
// Generate this function as it may be used
|
||||||
@@ -599,13 +589,13 @@ void TemplateDeclaration::semantic(Scope *sc)
|
|||||||
// FIXME: LDC
|
// FIXME: LDC
|
||||||
// sc->module->toModuleUnittest();
|
// sc->module->toModuleUnittest();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Remember Scope for later instantiations, but make
|
/* Remember Scope for later instantiations, but make
|
||||||
* a copy since attributes can change.
|
* a copy since attributes can change.
|
||||||
*/
|
*/
|
||||||
if (!this->scope)
|
if (!this->scope)
|
||||||
{ this->scope = new Scope(*sc);
|
{
|
||||||
|
this->scope = new Scope(*sc);
|
||||||
this->scope->setNoFree();
|
this->scope->setNoFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,6 +608,9 @@ void TemplateDeclaration::semantic(Scope *sc)
|
|||||||
if (!parent)
|
if (!parent)
|
||||||
parent = sc->parent;
|
parent = sc->parent;
|
||||||
|
|
||||||
|
isstatic = toParent()->isModule() ||
|
||||||
|
toParent()->isFuncDeclaration() && (scope->stc & STCstatic);
|
||||||
|
|
||||||
protection = sc->protection;
|
protection = sc->protection;
|
||||||
|
|
||||||
if (global.params.doDocComments)
|
if (global.params.doDocComments)
|
||||||
@@ -644,7 +637,8 @@ void TemplateDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
tp->semantic(paramscope, parameters);
|
tp->semantic(paramscope, parameters);
|
||||||
if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
|
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;
|
errors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -904,7 +898,6 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (m && constraint && !flag)
|
if (m && constraint && !flag)
|
||||||
{
|
{
|
||||||
/* Check to see if constraint is satisfied.
|
/* Check to see if constraint is satisfied.
|
||||||
@@ -979,16 +972,15 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti,
|
|||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
|
|
||||||
e = e->ctfeInterpret();
|
e = e->ctfeInterpret();
|
||||||
if (e->isBool(TRUE))
|
if (e->isBool(true))
|
||||||
;
|
;
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
|
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LOGM
|
#if LOGM
|
||||||
// Print out the results
|
// Print out the results
|
||||||
@@ -1135,8 +1127,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
|
|||||||
unsigned wildmatch = 0;
|
unsigned wildmatch = 0;
|
||||||
TemplateParameters *inferparams = parameters;
|
TemplateParameters *inferparams = parameters;
|
||||||
|
|
||||||
TypeFunction *tf = (TypeFunction *)fd->type;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
|
printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
|
||||||
for (size_t i = 0; i < (fargs ? fargs->dim : 0); i++)
|
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.setDim(parameters->dim);
|
||||||
dedtypes.zero();
|
dedtypes.zero();
|
||||||
|
|
||||||
if (errors)
|
if (errors || f->errors)
|
||||||
return MATCHnomatch;
|
return MATCHnomatch;
|
||||||
|
|
||||||
// Set up scope for parameters
|
// Set up scope for parameters
|
||||||
@@ -1222,11 +1212,10 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
|
|||||||
|
|
||||||
for (size_t i = 0; i < n; i++)
|
for (size_t i = 0; i < n; i++)
|
||||||
{ assert(i < parameters->dim);
|
{ assert(i < parameters->dim);
|
||||||
TemplateParameter *tp = (*parameters)[i];
|
|
||||||
MATCH m;
|
MATCH m;
|
||||||
Declaration *sparam = NULL;
|
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);
|
//printf("\tdeduceType m = %d\n", m);
|
||||||
if (m == MATCHnomatch)
|
if (m == MATCHnomatch)
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
@@ -1312,15 +1301,14 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (tthis)
|
if (tthis)
|
||||||
{
|
{
|
||||||
bool hasttp = false;
|
bool hasttp = false;
|
||||||
|
|
||||||
// Match 'tthis' to any TemplateThisParameter's
|
// Match 'tthis' to any TemplateThisParameter's
|
||||||
for (size_t i = 0; i < parameters->dim; i++)
|
for (size_t i = 0; i < parameters->dim; i++)
|
||||||
{ TemplateParameter *tp = (*parameters)[i];
|
{
|
||||||
TemplateThisParameter *ttp = tp->isTemplateThisParameter();
|
TemplateThisParameter *ttp = (*parameters)[i]->isTemplateThisParameter();
|
||||||
if (ttp)
|
if (ttp)
|
||||||
{ hasttp = true;
|
{ hasttp = true;
|
||||||
|
|
||||||
@@ -1336,7 +1324,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
|
|||||||
// Match attributes of tthis against attributes of fd
|
// Match attributes of tthis against attributes of fd
|
||||||
if (fd->type && !fd->isCtorDeclaration())
|
if (fd->type && !fd->isCtorDeclaration())
|
||||||
{
|
{
|
||||||
unsigned mod = fd->type->mod;
|
unsigned char mod = fd->type->mod;
|
||||||
StorageClass stc = scope->stc | fd->storage_class2;
|
StorageClass stc = scope->stc | fd->storage_class2;
|
||||||
// Propagate parent storage class (see bug 5504)
|
// Propagate parent storage class (see bug 5504)
|
||||||
Dsymbol *p = parent;
|
Dsymbol *p = parent;
|
||||||
@@ -1360,7 +1348,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
|
|||||||
if (mod & MODconst)
|
if (mod & MODconst)
|
||||||
mod &= ~STCwild;
|
mod &= ~STCwild;
|
||||||
|
|
||||||
unsigned thismod = tthis->mod;
|
unsigned char thismod = tthis->mod;
|
||||||
if (hasttp)
|
if (hasttp)
|
||||||
mod = MODmerge(thismod, mod);
|
mod = MODmerge(thismod, mod);
|
||||||
if (thismod != mod)
|
if (thismod != mod)
|
||||||
@@ -1372,7 +1360,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Loop through the function parameters
|
// Loop through the function parameters
|
||||||
{
|
{
|
||||||
@@ -1667,7 +1654,6 @@ Lretry:
|
|||||||
#endif
|
#endif
|
||||||
Type *argtype = farg->type;
|
Type *argtype = farg->type;
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
/* Allow expressions that have CT-known boundaries and type [] to match with [dim]
|
/* Allow expressions that have CT-known boundaries and type [] to match with [dim]
|
||||||
*/
|
*/
|
||||||
Type *taai;
|
Type *taai;
|
||||||
@@ -1699,8 +1685,7 @@ Lretry:
|
|||||||
*/
|
*/
|
||||||
if (farg->op == TOKfunction)
|
if (farg->op == TOKfunction)
|
||||||
{ FuncExp *fe = (FuncExp *)farg;
|
{ FuncExp *fe = (FuncExp *)farg;
|
||||||
Type *tp = prmtype;
|
Expression *e = fe->inferType(prmtype, 1, paramscope, inferparams);
|
||||||
Expression *e = fe->inferType(tp, 1, paramscope, inferparams);
|
|
||||||
if (!e)
|
if (!e)
|
||||||
goto Lvarargs;
|
goto Lvarargs;
|
||||||
farg = e;
|
farg = e;
|
||||||
@@ -1719,7 +1704,6 @@ Lretry:
|
|||||||
{
|
{
|
||||||
argtype = argtype->mutableOf();
|
argtype = argtype->mutableOf();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fvarargs == 2 && parami + 1 == nfparams && argi + 1 < nfargs)
|
if (fvarargs == 2 && parami + 1 == nfparams && argi + 1 < nfargs)
|
||||||
goto Lvarargs;
|
goto Lvarargs;
|
||||||
@@ -1741,7 +1725,6 @@ Lretry:
|
|||||||
if (!m)
|
if (!m)
|
||||||
{ Type *tbp = prmtype->toBasetype();
|
{ Type *tbp = prmtype->toBasetype();
|
||||||
Type *tba = farg->type->toBasetype();
|
Type *tba = farg->type->toBasetype();
|
||||||
AggregateDeclaration *ad;
|
|
||||||
if (tbp->ty == Tdelegate)
|
if (tbp->ty == Tdelegate)
|
||||||
{
|
{
|
||||||
TypeDelegate *td = (TypeDelegate *)prmtype->toBasetype();
|
TypeDelegate *td = (TypeDelegate *)prmtype->toBasetype();
|
||||||
@@ -1755,23 +1738,18 @@ Lretry:
|
|||||||
}
|
}
|
||||||
//printf("\tm2 = %d\n", m);
|
//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 (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.
|
* eg purity(bug 7295), just regard it as not a match.
|
||||||
*/
|
*/
|
||||||
unsigned olderrors = global.startGagging();
|
unsigned olderrors = global.startGagging();
|
||||||
Expression *e = resolveAliasThis(sc, farg);
|
Expression *e = resolveAliasThis(sc, farg);
|
||||||
if (!global.endGagging(olderrors))
|
if (!global.endGagging(olderrors))
|
||||||
{ farg = e;
|
{
|
||||||
|
farg = e;
|
||||||
goto Lretry;
|
goto Lretry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1881,9 +1859,8 @@ Lretry:
|
|||||||
|
|
||||||
if (arg->op == TOKfunction)
|
if (arg->op == TOKfunction)
|
||||||
{ FuncExp *fe = (FuncExp *)arg;
|
{ 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)
|
if (!e)
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
arg = e;
|
arg = e;
|
||||||
@@ -1992,7 +1969,6 @@ Lmatch:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (constraint)
|
if (constraint)
|
||||||
{
|
{
|
||||||
/* Check to see if constraint is satisfied.
|
/* Check to see if constraint is satisfied.
|
||||||
@@ -2037,7 +2013,6 @@ Lmatch:
|
|||||||
|
|
||||||
int nerrors = global.errors;
|
int nerrors = global.errors;
|
||||||
|
|
||||||
FuncDeclaration *fd = f;
|
|
||||||
Dsymbol *s = parent;
|
Dsymbol *s = parent;
|
||||||
while (s->isTemplateInstance() || s->isTemplateMixin())
|
while (s->isTemplateInstance() || s->isTemplateMixin())
|
||||||
s = s->parent;
|
s = s->parent;
|
||||||
@@ -2066,16 +2041,15 @@ Lmatch:
|
|||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
|
|
||||||
e = e->ctfeInterpret();
|
e = e->ctfeInterpret();
|
||||||
if (e->isBool(TRUE))
|
if (e->isBool(true))
|
||||||
;
|
;
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(false))
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
|
e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
for (i = 0; i < dedargs->dim; i++)
|
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)
|
static int fp(void *param, Dsymbol *s)
|
||||||
{
|
{
|
||||||
if (FuncDeclaration *fd = s->isFuncDeclaration())
|
if (!s->errors)
|
||||||
return ((ParamDeduce *)param)->fp(fd);
|
{
|
||||||
if (TemplateDeclaration *td = s->isTemplateDeclaration())
|
if (FuncDeclaration *fd = s->isFuncDeclaration())
|
||||||
return ((ParamDeduce *)param)->fp(td);
|
return ((ParamDeduce *)param)->fp(fd);
|
||||||
|
if (TemplateDeclaration *td = s->isTemplateDeclaration())
|
||||||
|
return ((ParamDeduce *)param)->fp(td);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int fp(FuncDeclaration *fd)
|
int fp(FuncDeclaration *fd)
|
||||||
@@ -2378,7 +2355,11 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
|
|||||||
if (td->semanticRun == PASSinit)
|
if (td->semanticRun == PASSinit)
|
||||||
{
|
{
|
||||||
::error(loc, "forward reference to template %s", td->toChars());
|
::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;
|
FuncDeclaration *f;
|
||||||
f = td->onemember ? td->onemember/*->toAlias()*/->isFuncDeclaration() : NULL;
|
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
|
// Disambiguate by tf->callMatch
|
||||||
TypeFunction *tf1 = (TypeFunction *)fd->type;
|
TypeFunction *tf1 = (TypeFunction *)fd->type;
|
||||||
|
assert(tf1->ty == Tfunction);
|
||||||
TypeFunction *tf2 = (TypeFunction *)m->lastf->type;
|
TypeFunction *tf2 = (TypeFunction *)m->lastf->type;
|
||||||
|
assert(tf2->ty == Tfunction);
|
||||||
MATCH c1 = tf1->callMatch(tthis_fd, fargs);
|
MATCH c1 = tf1->callMatch(tthis_fd, fargs);
|
||||||
MATCH c2 = tf2->callMatch(tthis_best, fargs);
|
MATCH c2 = tf2->callMatch(tthis_best, fargs);
|
||||||
//printf("2: c1 = %d, c2 = %d\n", c1, c2);
|
//printf("2: c1 = %d, c2 = %d\n", c1, c2);
|
||||||
@@ -2542,12 +2525,6 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Lerror:
|
|
||||||
m->lastf = NULL;
|
|
||||||
m->count = 0;
|
|
||||||
m->last = MATCHnomatch;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ParamDeduce p;
|
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;
|
p.tthis_best = m->lastf->needThis() && !m->lastf->isCtorDeclaration() ? tthis : NULL;
|
||||||
|
|
||||||
TypeFunction *tf = (TypeFunction *)m->lastf->type;
|
TypeFunction *tf = (TypeFunction *)m->lastf->type;
|
||||||
|
if (tf->ty == Terror)
|
||||||
|
goto Lerror;
|
||||||
assert(tf->ty == Tfunction);
|
assert(tf->ty == Tfunction);
|
||||||
if (!tf->callMatch(p.tthis_best, fargs))
|
if (!tf->callMatch(p.tthis_best, fargs))
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
@@ -2719,15 +2698,15 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
|
|||||||
sc2->tinst = ti;
|
sc2->tinst = ti;
|
||||||
|
|
||||||
{
|
{
|
||||||
Scope *sc = sc2;
|
Scope *scx = sc2;
|
||||||
sc = sc->push();
|
scx = scx->push();
|
||||||
|
|
||||||
if (hasttp)
|
if (hasttp)
|
||||||
fd->type = fd->type->addMod(tthis->mod);
|
fd->type = fd->type->addMod(tthis->mod);
|
||||||
//printf("tthis = %s, fdtype = %s\n", tthis->toChars(), fd->type->toChars());
|
//printf("tthis = %s, fdtype = %s\n", tthis->toChars(), fd->type->toChars());
|
||||||
if (fd->isCtorDeclaration())
|
if (fd->isCtorDeclaration())
|
||||||
{
|
{
|
||||||
sc->flags |= SCOPEctor;
|
scx->flags |= SCOPEctor;
|
||||||
|
|
||||||
Dsymbol *parent = toParent2();
|
Dsymbol *parent = toParent2();
|
||||||
Type *tret;
|
Type *tret;
|
||||||
@@ -2739,7 +2718,7 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
|
|||||||
else
|
else
|
||||||
{ tret = ad->handle;
|
{ tret = ad->handle;
|
||||||
assert(tret);
|
assert(tret);
|
||||||
tret = tret->addStorageClass(fd->storage_class | sc->stc);
|
tret = tret->addStorageClass(fd->storage_class | scx->stc);
|
||||||
tret = tret->addMod(fd->type->mod);
|
tret = tret->addMod(fd->type->mod);
|
||||||
}
|
}
|
||||||
((TypeFunction *)fd->type)->next = tret;
|
((TypeFunction *)fd->type)->next = tret;
|
||||||
@@ -2747,9 +2726,9 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
|
|||||||
((TypeFunction *)fd->type)->isref = 1;
|
((TypeFunction *)fd->type)->isref = 1;
|
||||||
//printf("fd->type = %s\n", fd->type->toChars());
|
//printf("fd->type = %s\n", fd->type->toChars());
|
||||||
}
|
}
|
||||||
fd->type = fd->type->addSTC(sc->stc);
|
fd->type = fd->type->addSTC(scx->stc);
|
||||||
fd->type = fd->type->semantic(fd->loc, sc);
|
fd->type = fd->type->semantic(fd->loc, scx);
|
||||||
sc = sc->pop();
|
scx = scx->pop();
|
||||||
}
|
}
|
||||||
//printf("\t[%s] fd->type = %s, mod = %x, ", loc.toChars(), fd->type->toChars(), fd->type->mod);
|
//printf("\t[%s] fd->type = %s, mod = %x, ", loc.toChars(), fd->type->toChars(), fd->type->mod);
|
||||||
//printf("fd->needThis() = %d\n", fd->needThis());
|
//printf("fd->needThis() = %d\n", fd->needThis());
|
||||||
@@ -2757,12 +2736,12 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
|
|||||||
sc2->pop();
|
sc2->pop();
|
||||||
scope->pop();
|
scope->pop();
|
||||||
|
|
||||||
return fd;
|
return fd->type->ty == Tfunction ? fd : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TemplateDeclaration::hasStaticCtorOrDtor()
|
bool TemplateDeclaration::hasStaticCtorOrDtor()
|
||||||
{
|
{
|
||||||
return FALSE; // don't scan uninstantiated templates
|
return false; // don't scan uninstantiated templates
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||||
@@ -2771,6 +2750,88 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
if (onemember && onemember->isFuncDeclaration())
|
if (onemember && onemember->isFuncDeclaration())
|
||||||
buf->writestring("foo ");
|
buf->writestring("foo ");
|
||||||
#endif
|
#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)
|
if (hgs->ddoc)
|
||||||
buf->writestring(kind());
|
buf->writestring(kind());
|
||||||
else
|
else
|
||||||
@@ -2788,13 +2849,12 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
tp->toCBuffer(buf, hgs);
|
tp->toCBuffer(buf, hgs);
|
||||||
}
|
}
|
||||||
buf->writeByte(')');
|
buf->writeByte(')');
|
||||||
#if DMDV2
|
|
||||||
if (constraint)
|
if (constraint)
|
||||||
{ buf->writestring(" if (");
|
{
|
||||||
|
buf->writestring(" if (");
|
||||||
constraint->toCBuffer(buf, hgs);
|
constraint->toCBuffer(buf, hgs);
|
||||||
buf->writeByte(')');
|
buf->writeByte(')');
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (hgs->hdrgen)
|
if (hgs->hdrgen)
|
||||||
{
|
{
|
||||||
@@ -2817,7 +2877,11 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
|
|
||||||
|
|
||||||
char *TemplateDeclaration::toChars()
|
char *TemplateDeclaration::toChars()
|
||||||
{ OutBuffer buf;
|
{
|
||||||
|
if (literal)
|
||||||
|
return Dsymbol::toChars();
|
||||||
|
|
||||||
|
OutBuffer buf;
|
||||||
HdrGenState hgs;
|
HdrGenState hgs;
|
||||||
|
|
||||||
memset(&hgs, 0, sizeof(hgs));
|
memset(&hgs, 0, sizeof(hgs));
|
||||||
@@ -2833,7 +2897,8 @@ char *TemplateDeclaration::toChars()
|
|||||||
buf.writeByte(')');
|
buf.writeByte(')');
|
||||||
|
|
||||||
if (onemember)
|
if (onemember)
|
||||||
{ /* Bugzilla 9406:
|
{
|
||||||
|
/* Bugzilla 9406:
|
||||||
* onemember->toAlias() might run semantic, so should not call it in stringizing
|
* onemember->toAlias() might run semantic, so should not call it in stringizing
|
||||||
*/
|
*/
|
||||||
FuncDeclaration *fd = onemember->isFuncDeclaration();
|
FuncDeclaration *fd = onemember->isFuncDeclaration();
|
||||||
@@ -2845,13 +2910,12 @@ char *TemplateDeclaration::toChars()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
if (constraint)
|
if (constraint)
|
||||||
{ buf.writestring(" if (");
|
{
|
||||||
|
buf.writestring(" if (");
|
||||||
constraint->toCBuffer(&buf, &hgs);
|
constraint->toCBuffer(&buf, &hgs);
|
||||||
buf.writeByte(')');
|
buf.writeByte(')');
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
buf.writeByte(0);
|
buf.writeByte(0);
|
||||||
return (char *)buf.extractData();
|
return (char *)buf.extractData();
|
||||||
}
|
}
|
||||||
@@ -3348,7 +3412,12 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
|||||||
|
|
||||||
if (ty != tparam->ty)
|
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
|
// Can't instantiate AssociativeArray!() without a scope
|
||||||
if (tparam->ty == Taarray && !((TypeAArray*)tparam)->sc)
|
if (tparam->ty == Taarray && !((TypeAArray*)tparam)->sc)
|
||||||
((TypeAArray*)tparam)->sc = 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);
|
m = at->deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
#else
|
|
||||||
return implicitConvTo(tparam);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextOf())
|
if (nextOf())
|
||||||
@@ -3380,13 +3446,10 @@ Lexact:
|
|||||||
Lnomatch:
|
Lnomatch:
|
||||||
return MATCHnomatch;
|
return MATCHnomatch;
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
Lconst:
|
Lconst:
|
||||||
return MATCHconst;
|
return MATCHconst;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||||
Objects *dedtypes, unsigned *wildmatch)
|
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);
|
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||||
Objects *dedtypes, unsigned *wildmatch)
|
Objects *dedtypes, unsigned *wildmatch)
|
||||||
{
|
{
|
||||||
@@ -3414,7 +3475,6 @@ MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
|
|||||||
#endif
|
#endif
|
||||||
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
||||||
Objects *dedtypes, unsigned *wildmatch)
|
Objects *dedtypes, unsigned *wildmatch)
|
||||||
@@ -3628,12 +3688,12 @@ MATCH TypeInstance::deduceType(Scope *sc,
|
|||||||
printf("\tthis = %d, ", ty); print();
|
printf("\tthis = %d, ", ty); print();
|
||||||
printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
printf("\ttparam = %d, ", tparam->ty); tparam->print();
|
||||||
#endif
|
#endif
|
||||||
TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration();
|
|
||||||
assert(tempdecl);
|
|
||||||
|
|
||||||
// Extra check
|
// 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;
|
TypeInstance *tp = (TypeInstance *)tparam;
|
||||||
|
|
||||||
//printf("tempinst->tempdecl = %p\n", tempdecl);
|
//printf("tempinst->tempdecl = %p\n", tempdecl);
|
||||||
@@ -3816,8 +3876,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
|
|||||||
goto Le;
|
goto Le;
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
}
|
}
|
||||||
TemplateParameter *tp = (*parameters)[j];
|
if (!(*parameters)[j]->matchArg(sc, e1, j, parameters, dedtypes, NULL))
|
||||||
if (!tp->matchArg(sc, e1, j, parameters, dedtypes, NULL))
|
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
}
|
}
|
||||||
else if (s1 && s2)
|
else if (s1 && s2)
|
||||||
@@ -3836,8 +3895,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
|
|||||||
goto Ls;
|
goto Ls;
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
}
|
}
|
||||||
TemplateParameter *tp = (*parameters)[j];
|
if (!(*parameters)[j]->matchArg(sc, s1, j, parameters, dedtypes, NULL))
|
||||||
if (!tp->matchArg(sc, s1, j, parameters, dedtypes, NULL))
|
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3899,6 +3957,8 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
|
|||||||
TypeStruct *tp = (TypeStruct *)tparam;
|
TypeStruct *tp = (TypeStruct *)tparam;
|
||||||
|
|
||||||
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
|
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
|
||||||
|
if (wildmatch && wildConvTo(tparam))
|
||||||
|
return MATCHconst;
|
||||||
return implicitConvTo(tp);
|
return implicitConvTo(tp);
|
||||||
}
|
}
|
||||||
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
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;
|
TypeClass *tp = (TypeClass *)tparam;
|
||||||
|
|
||||||
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
|
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
|
||||||
|
if (wildmatch && wildConvTo(tparam))
|
||||||
|
return MATCHconst;
|
||||||
return implicitConvTo(tp);
|
return implicitConvTo(tp);
|
||||||
}
|
}
|
||||||
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
|
||||||
@@ -4118,12 +4180,10 @@ TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
TemplateThisParameter *TemplateParameter::isTemplateThisParameter()
|
TemplateThisParameter *TemplateParameter::isTemplateThisParameter()
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*******************************************
|
/*******************************************
|
||||||
* Match to a particular TemplateParameter.
|
* Match to a particular TemplateParameter.
|
||||||
@@ -4343,12 +4403,13 @@ void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
|
|
||||||
|
|
||||||
void *TemplateTypeParameter::dummyArg()
|
void *TemplateTypeParameter::dummyArg()
|
||||||
{ Type *t;
|
{
|
||||||
|
Type *t;
|
||||||
if (specType)
|
if (specType)
|
||||||
t = specType;
|
t = specType;
|
||||||
else
|
else
|
||||||
{ // Use this for alias-parameter's too (?)
|
{
|
||||||
|
// Use this for alias-parameter's too (?)
|
||||||
if (!tdummy)
|
if (!tdummy)
|
||||||
tdummy = new TypeIdentifier(loc, ident);
|
tdummy = new TypeIdentifier(loc, ident);
|
||||||
t = tdummy;
|
t = tdummy;
|
||||||
@@ -4378,7 +4439,6 @@ RootObject *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
|
|||||||
|
|
||||||
/* ======================== TemplateThisParameter =========================== */
|
/* ======================== TemplateThisParameter =========================== */
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
// this-parameter
|
// this-parameter
|
||||||
|
|
||||||
TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident,
|
TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident,
|
||||||
@@ -4408,7 +4468,6 @@ void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring("this ");
|
buf->writestring("this ");
|
||||||
TemplateTypeParameter::toCBuffer(buf, hgs);
|
TemplateTypeParameter::toCBuffer(buf, hgs);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ======================== TemplateAliasParameter ========================== */
|
/* ======================== TemplateAliasParameter ========================== */
|
||||||
|
|
||||||
@@ -4982,9 +5041,7 @@ RootObject *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
|
|||||||
e = e->syntaxCopy();
|
e = e->syntaxCopy();
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
e = resolveProperties(sc, e);
|
e = resolveProperties(sc, e);
|
||||||
#if DMDV2
|
|
||||||
e = e->resolveLoc(loc, sc);
|
e = e->resolveLoc(loc, sc);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -5151,6 +5208,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
|
|||||||
this->instantiatingModule = NULL;
|
this->instantiatingModule = NULL;
|
||||||
this->inst = NULL;
|
this->inst = NULL;
|
||||||
this->tinst = NULL;
|
this->tinst = NULL;
|
||||||
|
this->deferred = NULL;
|
||||||
this->argsym = NULL;
|
this->argsym = NULL;
|
||||||
this->aliasdecl = NULL;
|
this->aliasdecl = NULL;
|
||||||
this->semantictiargsdone = false;
|
this->semantictiargsdone = false;
|
||||||
@@ -5185,6 +5243,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
|
|||||||
this->instantiatingModule = NULL;
|
this->instantiatingModule = NULL;
|
||||||
this->inst = NULL;
|
this->inst = NULL;
|
||||||
this->tinst = NULL;
|
this->tinst = NULL;
|
||||||
|
this->deferred = NULL;
|
||||||
this->argsym = NULL;
|
this->argsym = NULL;
|
||||||
this->aliasdecl = NULL;
|
this->aliasdecl = NULL;
|
||||||
this->semantictiargsdone = true;
|
this->semantictiargsdone = true;
|
||||||
@@ -5246,9 +5305,11 @@ void TemplateInstance::semantic(Scope *sc)
|
|||||||
void TemplateInstance::expandMembers(Scope *sc2)
|
void TemplateInstance::expandMembers(Scope *sc2)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{ Dsymbol *s = (*members)[i];
|
{
|
||||||
|
Dsymbol *s = (*members)[i];
|
||||||
s->setScope(sc2);
|
s->setScope(sc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = (*members)[i];
|
Dsymbol *s = (*members)[i];
|
||||||
@@ -5402,7 +5463,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
|||||||
if (tempdecl->ismixin)
|
if (tempdecl->ismixin)
|
||||||
error("mixin templates are not regular templates");
|
error("mixin templates are not regular templates");
|
||||||
|
|
||||||
hasNestedArgs(tiargs);
|
hasNestedArgs(tiargs, tempdecl->isstatic);
|
||||||
|
|
||||||
arrayCheckRecursiveExpansion(&tdtypes, tempdecl, sc);
|
arrayCheckRecursiveExpansion(&tdtypes, tempdecl, sc);
|
||||||
|
|
||||||
@@ -5521,10 +5582,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
|||||||
Module *m = (Module *)s;
|
Module *m = (Module *)s;
|
||||||
if (!m->isRoot())
|
if (!m->isRoot())
|
||||||
{
|
{
|
||||||
//if (tinst && tinst->objFileModule)
|
m = m->importedFrom;
|
||||||
// m = tinst->objFileModule;
|
|
||||||
//else
|
|
||||||
m = m->importedFrom;
|
|
||||||
}
|
}
|
||||||
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
|
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
|
||||||
a = m->members;
|
a = m->members;
|
||||||
@@ -5551,7 +5609,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Copy the syntax trees from the TemplateDeclaration
|
// Copy the syntax trees from the TemplateDeclaration
|
||||||
if (members && speculative)
|
if (members && speculative && !errors)
|
||||||
{} // Don't copy again so they were previously created.
|
{} // Don't copy again so they were previously created.
|
||||||
else
|
else
|
||||||
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
|
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
|
||||||
@@ -5680,6 +5738,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
|||||||
sc2->parent = /*enclosing ? sc->parent :*/ this;
|
sc2->parent = /*enclosing ? sc->parent :*/ this;
|
||||||
sc2->tinst = this;
|
sc2->tinst = this;
|
||||||
sc2->speculative = speculative;
|
sc2->speculative = speculative;
|
||||||
|
if (enclosing && tempdecl->isstatic)
|
||||||
|
sc2->stc &= ~STCstatic;
|
||||||
|
|
||||||
tryExpandMembers(sc2);
|
tryExpandMembers(sc2);
|
||||||
|
|
||||||
@@ -5743,10 +5803,64 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
|||||||
semantic2(sc2);
|
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);
|
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:
|
Laftersemantic:
|
||||||
sc2->pop();
|
sc2->pop();
|
||||||
@@ -5756,7 +5870,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
|||||||
// Give additional context info if error occurred during instantiation
|
// Give additional context info if error occurred during instantiation
|
||||||
if (global.errors != errorsave)
|
if (global.errors != errorsave)
|
||||||
{
|
{
|
||||||
error(loc, "error instantiating");
|
if (!tempdecl->literal)
|
||||||
|
error(loc, "error instantiating");
|
||||||
if (tinst)
|
if (tinst)
|
||||||
{ tinst->printInstantiationTrace();
|
{ tinst->printInstantiationTrace();
|
||||||
}
|
}
|
||||||
@@ -6571,7 +6686,7 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag)
|
|||||||
* Sets enclosing property if so, and returns != 0;
|
* Sets enclosing property if so, and returns != 0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool TemplateInstance::hasNestedArgs(Objects *args)
|
bool TemplateInstance::hasNestedArgs(Objects *args, bool isstatic)
|
||||||
{
|
{
|
||||||
int nested = 0;
|
int nested = 0;
|
||||||
//printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars());
|
//printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars());
|
||||||
@@ -6656,15 +6771,13 @@ bool TemplateInstance::hasNestedArgs(Objects *args)
|
|||||||
(ad && ad->isNested()) ||
|
(ad && ad->isNested()) ||
|
||||||
#endif
|
#endif
|
||||||
(d && !d->isDataseg() &&
|
(d && !d->isDataseg() &&
|
||||||
#if DMDV2
|
|
||||||
!(d->storage_class & STCmanifest) &&
|
!(d->storage_class & STCmanifest) &&
|
||||||
#endif
|
|
||||||
(!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
|
(!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
|
||||||
!isTemplateMixin()
|
!isTemplateMixin()
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
// if module level template
|
// if module level template
|
||||||
if (tempdecl->toParent()->isModule())
|
if (isstatic)
|
||||||
{
|
{
|
||||||
Dsymbol *dparent = sa->toParent2();
|
Dsymbol *dparent = sa->toParent2();
|
||||||
if (!enclosing)
|
if (!enclosing)
|
||||||
@@ -6699,7 +6812,7 @@ bool TemplateInstance::hasNestedArgs(Objects *args)
|
|||||||
}
|
}
|
||||||
else if (va)
|
else if (va)
|
||||||
{
|
{
|
||||||
nested |= hasNestedArgs(&va->objects);
|
nested |= hasNestedArgs(&va->objects, isstatic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//printf("-TemplateInstance::hasNestedArgs('%s') = %d\n", tempdecl->ident->toChars(), nested);
|
//printf("-TemplateInstance::hasNestedArgs('%s') = %d\n", tempdecl->ident->toChars(), nested);
|
||||||
@@ -7058,6 +7171,8 @@ void TemplateInstance::toCBufferTiargs(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writeByte('!');
|
buf->writeByte('!');
|
||||||
if (nest)
|
if (nest)
|
||||||
buf->writestring("(...)");
|
buf->writestring("(...)");
|
||||||
|
else if (!tiargs)
|
||||||
|
buf->writestring("()");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tiargs->dim == 1)
|
if (tiargs->dim == 1)
|
||||||
@@ -7192,7 +7307,7 @@ int TemplateInstance::compare(RootObject *o)
|
|||||||
if (fargs)
|
if (fargs)
|
||||||
{
|
{
|
||||||
FuncDeclaration *fd = ti->toAlias()->isFuncDeclaration();
|
FuncDeclaration *fd = ti->toAlias()->isFuncDeclaration();
|
||||||
if (fd)
|
if (fd && !fd->errors)
|
||||||
{
|
{
|
||||||
Parameters *fparameters = fd->getParameters(NULL);
|
Parameters *fparameters = fd->getParameters(NULL);
|
||||||
size_t nfparams = Parameter::dim(fparameters); // Num function parameters
|
size_t nfparams = Parameter::dim(fparameters); // Num function parameters
|
||||||
@@ -7200,8 +7315,6 @@ int TemplateInstance::compare(RootObject *o)
|
|||||||
{
|
{
|
||||||
Parameter *fparam = Parameter::getNth(fparameters, j);
|
Parameter *fparam = Parameter::getNth(fparameters, j);
|
||||||
Expression *farg = (*fargs)[j];
|
Expression *farg = (*fargs)[j];
|
||||||
if (Expression *e = farg->isTemp())
|
|
||||||
farg = e;
|
|
||||||
if (fparam->storageClass & STCauto) // if "auto ref"
|
if (fparam->storageClass & STCauto) // if "auto ref"
|
||||||
{
|
{
|
||||||
if (farg->isLvalue())
|
if (farg->isLvalue())
|
||||||
@@ -7278,18 +7391,18 @@ bool TemplateMixin::findTemplateDeclaration(Scope *sc)
|
|||||||
*/
|
*/
|
||||||
if (os)
|
if (os)
|
||||||
{
|
{
|
||||||
Dsymbol *s = NULL;
|
Dsymbol *ds = NULL;
|
||||||
for (size_t i = 0; i < os->a.dim; i++)
|
for (size_t i = 0; i < os->a.dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s2 = os->a[i]->isTemplateDeclaration();
|
Dsymbol *s2 = os->a[i]->isTemplateDeclaration();
|
||||||
if (s2)
|
if (s2)
|
||||||
{
|
{
|
||||||
if (s)
|
if (ds)
|
||||||
{
|
{
|
||||||
tempdecl = os;
|
tempdecl = os;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s = s2;
|
ds = s2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7467,7 +7580,7 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy the syntax trees from the TemplateDeclaration
|
// Copy the syntax trees from the TemplateDeclaration
|
||||||
if (scx && members)
|
if (scx && members && !errors)
|
||||||
{} // Don't copy again so they were previously created.
|
{} // Don't copy again so they were previously created.
|
||||||
else
|
else
|
||||||
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
|
members = Dsymbol::arraySyntaxCopy(tempdecl->members);
|
||||||
@@ -7529,6 +7642,12 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
fatal();
|
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++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = (*members)[i];
|
Dsymbol *s = (*members)[i];
|
||||||
@@ -7580,6 +7699,7 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
if (global.errors != errorsave)
|
if (global.errors != errorsave)
|
||||||
{
|
{
|
||||||
error("error instantiating");
|
error("error instantiating");
|
||||||
|
errors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc2->pop();
|
sc2->pop();
|
||||||
|
|||||||
+7
-14
@@ -71,8 +71,9 @@ public:
|
|||||||
|
|
||||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||||
|
|
||||||
int literal; // this template declaration is a literal
|
bool literal; // this template declaration is a literal
|
||||||
int ismixin; // template declaration is only to be used as a mixin
|
bool ismixin; // template declaration is only to be used as a mixin
|
||||||
|
bool isstatic; // this is static template declaration
|
||||||
PROT protection;
|
PROT protection;
|
||||||
|
|
||||||
struct Previous
|
struct Previous
|
||||||
@@ -83,7 +84,7 @@ public:
|
|||||||
Previous *previous; // threaded list of previous instantiation attempts on stack
|
Previous *previous; // threaded list of previous instantiation attempts on stack
|
||||||
|
|
||||||
TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters,
|
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 *);
|
Dsymbol *syntaxCopy(Dsymbol *);
|
||||||
void semantic(Scope *sc);
|
void semantic(Scope *sc);
|
||||||
bool overloadInsert(Dsymbol *s);
|
bool overloadInsert(Dsymbol *s);
|
||||||
@@ -145,9 +146,7 @@ public:
|
|||||||
virtual TemplateTypeParameter *isTemplateTypeParameter();
|
virtual TemplateTypeParameter *isTemplateTypeParameter();
|
||||||
virtual TemplateValueParameter *isTemplateValueParameter();
|
virtual TemplateValueParameter *isTemplateValueParameter();
|
||||||
virtual TemplateAliasParameter *isTemplateAliasParameter();
|
virtual TemplateAliasParameter *isTemplateAliasParameter();
|
||||||
#if DMDV2
|
|
||||||
virtual TemplateThisParameter *isTemplateThisParameter();
|
virtual TemplateThisParameter *isTemplateThisParameter();
|
||||||
#endif
|
|
||||||
virtual TemplateTupleParameter *isTemplateTupleParameter();
|
virtual TemplateTupleParameter *isTemplateTupleParameter();
|
||||||
|
|
||||||
virtual TemplateParameter *syntaxCopy() = 0;
|
virtual TemplateParameter *syntaxCopy() = 0;
|
||||||
@@ -198,7 +197,6 @@ public:
|
|||||||
void *dummyArg();
|
void *dummyArg();
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
class TemplateThisParameter : public TemplateTypeParameter
|
class TemplateThisParameter : public TemplateTypeParameter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -212,7 +210,6 @@ public:
|
|||||||
TemplateParameter *syntaxCopy();
|
TemplateParameter *syntaxCopy();
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
class TemplateValueParameter : public TemplateParameter
|
class TemplateValueParameter : public TemplateParameter
|
||||||
{
|
{
|
||||||
@@ -324,12 +321,8 @@ public:
|
|||||||
hash_t hash; // cached result of hashCode()
|
hash_t hash; // cached result of hashCode()
|
||||||
Expressions *fargs; // for function template, these are the function arguments
|
Expressions *fargs; // for function template, these are the function arguments
|
||||||
Module *instantiatingModule; // the top module that instantiated this instance
|
Module *instantiatingModule; // the top module that instantiated this instance
|
||||||
#ifdef IN_GCC
|
|
||||||
/* On some targets, it is necessary to know whether a symbol
|
TemplateInstances* deferred;
|
||||||
will be emitted in the output or not before the symbol
|
|
||||||
is used. This can be different from getModule(). */
|
|
||||||
Module * objFileModule;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TemplateInstance(Loc loc, Identifier *temp_id);
|
TemplateInstance(Loc loc, Identifier *temp_id);
|
||||||
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
|
TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs);
|
||||||
@@ -363,7 +356,7 @@ public:
|
|||||||
bool semanticTiargs(Scope *sc);
|
bool semanticTiargs(Scope *sc);
|
||||||
bool findBestMatch(Scope *sc, Expressions *fargs);
|
bool findBestMatch(Scope *sc, Expressions *fargs);
|
||||||
bool needsTypeInference(Scope *sc, int flag = 0);
|
bool needsTypeInference(Scope *sc, int flag = 0);
|
||||||
bool hasNestedArgs(Objects *tiargs);
|
bool hasNestedArgs(Objects *tiargs, bool isstatic);
|
||||||
void declareParameters(Scope *sc);
|
void declareParameters(Scope *sc);
|
||||||
Identifier *genIdent(Objects *args);
|
Identifier *genIdent(Objects *args);
|
||||||
void expandMembers(Scope *sc);
|
void expandMembers(Scope *sc);
|
||||||
|
|||||||
+102
-67
@@ -38,7 +38,6 @@
|
|||||||
|
|
||||||
#define LOGSEMANTIC 0
|
#define LOGSEMANTIC 0
|
||||||
|
|
||||||
#if DMDV2
|
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
* Delegate to be passed to overloadApply() that looks
|
* 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)
|
static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions *unitTests)
|
||||||
{
|
{
|
||||||
|
if (!symbols)
|
||||||
|
return;
|
||||||
for (size_t i = 0; i < symbols->dim; i++)
|
for (size_t i = 0; i < symbols->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *symbol = (*symbols)[i];
|
Dsymbol *symbol = (*symbols)[i];
|
||||||
@@ -124,6 +125,81 @@ static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions
|
|||||||
|
|
||||||
/************************ TraitsExp ************************************/
|
/************************ 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)
|
Expression *TraitsExp::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
#if LOGSEMANTIC
|
#if LOGSEMANTIC
|
||||||
@@ -137,67 +213,41 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
size_t dim = args ? args->dim : 0;
|
size_t dim = args ? args->dim : 0;
|
||||||
Declaration *d;
|
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)
|
if (ident == Id::isArithmetic)
|
||||||
{
|
{
|
||||||
ISTYPE(t->isintegral() || t->isfloating())
|
return isTypeX(&isTypeArithmetic);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isFloating)
|
else if (ident == Id::isFloating)
|
||||||
{
|
{
|
||||||
ISTYPE(t->isfloating())
|
return isTypeX(&isTypeFloating);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isIntegral)
|
else if (ident == Id::isIntegral)
|
||||||
{
|
{
|
||||||
ISTYPE(t->isintegral())
|
return isTypeX(&isTypeIntegral);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isScalar)
|
else if (ident == Id::isScalar)
|
||||||
{
|
{
|
||||||
ISTYPE(t->isscalar())
|
return isTypeX(&isTypeScalar);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isUnsigned)
|
else if (ident == Id::isUnsigned)
|
||||||
{
|
{
|
||||||
ISTYPE(t->isunsigned())
|
return isTypeX(&isTypeUnsigned);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isAssociativeArray)
|
else if (ident == Id::isAssociativeArray)
|
||||||
{
|
{
|
||||||
ISTYPE(t->toBasetype()->ty == Taarray)
|
return isTypeX(&isTypeAssociativeArray);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isStaticArray)
|
else if (ident == Id::isStaticArray)
|
||||||
{
|
{
|
||||||
ISTYPE(t->toBasetype()->ty == Tsarray)
|
return isTypeX(&isTypeStaticArray);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isAbstractClass)
|
else if (ident == Id::isAbstractClass)
|
||||||
{
|
{
|
||||||
ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
|
return isTypeX(&isTypeAbstractClass);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isFinalClass)
|
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)
|
else if (ident == Id::isPOD)
|
||||||
{
|
{
|
||||||
@@ -251,41 +301,35 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
else if (ident == Id::isAbstractFunction)
|
else if (ident == Id::isAbstractFunction)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f;
|
return isFuncX(&isFuncAbstractFunction);
|
||||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
|
|
||||||
}
|
}
|
||||||
else if (ident == Id::isVirtualFunction)
|
else if (ident == Id::isVirtualFunction)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f;
|
return isFuncX(&isFuncVirtualFunction);
|
||||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
|
|
||||||
}
|
}
|
||||||
else if (ident == Id::isVirtualMethod)
|
else if (ident == Id::isVirtualMethod)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f;
|
return isFuncX(&isFuncVirtualMethod);
|
||||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtualMethod())
|
|
||||||
}
|
}
|
||||||
else if (ident == Id::isFinalFunction)
|
else if (ident == Id::isFinalFunction)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f;
|
return isFuncX(&isFuncFinalFunction);
|
||||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinalFunc())
|
|
||||||
}
|
}
|
||||||
#if DMDV2
|
|
||||||
else if (ident == Id::isStaticFunction)
|
else if (ident == Id::isStaticFunction)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f;
|
return isFuncX(&isFuncStaticFunction);
|
||||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis() && !f->isNested())
|
|
||||||
}
|
}
|
||||||
else if (ident == Id::isRef)
|
else if (ident == Id::isRef)
|
||||||
{
|
{
|
||||||
ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isRef())
|
return isDeclX(&isDeclRef);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isOut)
|
else if (ident == Id::isOut)
|
||||||
{
|
{
|
||||||
ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isOut())
|
return isDeclX(&isDeclOut);
|
||||||
}
|
}
|
||||||
else if (ident == Id::isLazy)
|
else if (ident == Id::isLazy)
|
||||||
{
|
{
|
||||||
ISDSYMBOL((d = s->isDeclaration()) != NULL && d->storage_class & STClazy)
|
return isDeclX(&isDeclLazy);
|
||||||
}
|
}
|
||||||
else if (ident == Id::identifier)
|
else if (ident == Id::identifier)
|
||||||
{ // Get identifier for symbol as a string literal
|
{ // Get identifier for symbol as a string literal
|
||||||
@@ -366,7 +410,6 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
return (new DsymbolExp(loc, s))->semantic(sc);
|
return (new DsymbolExp(loc, s))->semantic(sc);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else if (ident == Id::hasMember ||
|
else if (ident == Id::hasMember ||
|
||||||
ident == Id::getMember ||
|
ident == Id::getMember ||
|
||||||
ident == Id::getOverloads ||
|
ident == Id::getOverloads ||
|
||||||
@@ -614,16 +657,11 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
(*exps)[i] = se;
|
(*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.
|
/* Making this a tuple is more flexible, as it can be statically unrolled.
|
||||||
* To make an array literal, enclose __traits in [ ]:
|
* To make an array literal, enclose __traits in [ ]:
|
||||||
* [ __traits(allMembers, ...) ]
|
* [ __traits(allMembers, ...) ]
|
||||||
*/
|
*/
|
||||||
Expression *e = new TupleExp(loc, exps);
|
Expression *e = new TupleExp(loc, exps);
|
||||||
#endif
|
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -640,9 +678,9 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
unsigned errors = global.startGagging();
|
unsigned errors = global.startGagging();
|
||||||
unsigned oldspec = global.speculativeGag;
|
unsigned oldspec = global.speculativeGag;
|
||||||
global.speculativeGag = global.gag;
|
global.speculativeGag = global.gag;
|
||||||
sc = sc->push();
|
Scope *sc2 = sc->push();
|
||||||
sc->speculative = true;
|
sc2->speculative = true;
|
||||||
sc->flags = sc->enclosing->flags & ~SCOPEctfe; // inherit without CTFEing
|
sc2->flags = sc->flags & ~SCOPEctfe | SCOPEcompile;
|
||||||
bool err = false;
|
bool err = false;
|
||||||
|
|
||||||
RootObject *o = (*args)[i];
|
RootObject *o = (*args)[i];
|
||||||
@@ -651,10 +689,10 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
if (!e && t)
|
if (!e && t)
|
||||||
{
|
{
|
||||||
Dsymbol *s;
|
Dsymbol *s;
|
||||||
t->resolve(loc, sc, &e, &t, &s);
|
t->resolve(loc, sc2, &e, &t, &s);
|
||||||
if (t)
|
if (t)
|
||||||
{
|
{
|
||||||
t->semantic(loc, sc);
|
t->semantic(loc, sc2);
|
||||||
if (t->ty == Terror)
|
if (t->ty == Terror)
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
@@ -663,13 +701,13 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc2);
|
||||||
e = e->optimize(WANTvalue);
|
e = e->optimize(WANTvalue);
|
||||||
if (e->op == TOKerror)
|
if (e->op == TOKerror)
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = sc->pop();
|
sc2->pop();
|
||||||
global.speculativeGag = oldspec;
|
global.speculativeGag = oldspec;
|
||||||
if (global.endGagging(errors) || err)
|
if (global.endGagging(errors) || err)
|
||||||
{
|
{
|
||||||
@@ -770,8 +808,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
else if (ident == Id::isOverrideFunction)
|
else if (ident == Id::isOverrideFunction)
|
||||||
{
|
{
|
||||||
FuncDeclaration *f;
|
return isFuncX(&isFuncOverrideFunction);
|
||||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isOverride())
|
|
||||||
}
|
}
|
||||||
else if(ident == Id::getVirtualIndex)
|
else if(ident == Id::getVirtualIndex)
|
||||||
{
|
{
|
||||||
@@ -807,5 +844,3 @@ Lfalse:
|
|||||||
Ltrue:
|
Ltrue:
|
||||||
return new IntegerExp(loc, 1, Type::tbool);
|
return new IntegerExp(loc, 1, Type::tbool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
+9
-9
@@ -70,7 +70,7 @@ static std::string getOutputName(bool const sharedLib)
|
|||||||
if (Module::rootModule)
|
if (Module::rootModule)
|
||||||
result = Module::rootModule->toChars();
|
result = Module::rootModule->toChars();
|
||||||
else if (global.params.objfiles->dim)
|
else if (global.params.objfiles->dim)
|
||||||
result = FileName::removeExt(static_cast<char*>(global.params.objfiles->data[0]));
|
result = FileName::removeExt(static_cast<const char*>(global.params.objfiles->data[0]));
|
||||||
else
|
else
|
||||||
result = "a.out";
|
result = "a.out";
|
||||||
|
|
||||||
@@ -110,14 +110,14 @@ static int linkObjToBinaryGcc(bool sharedLib)
|
|||||||
// object files
|
// object files
|
||||||
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
||||||
{
|
{
|
||||||
char *p = static_cast<char *>(global.params.objfiles->data[i]);
|
const char *p = static_cast<const char *>(global.params.objfiles->data[i]);
|
||||||
args.push_back(p);
|
args.push_back(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// user libs
|
// user libs
|
||||||
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
|
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
|
||||||
{
|
{
|
||||||
char *p = static_cast<char *>(global.params.libfiles->data[i]);
|
const char *p = static_cast<const char *>(global.params.libfiles->data[i]);
|
||||||
args.push_back(p);
|
args.push_back(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ static int linkObjToBinaryGcc(bool sharedLib)
|
|||||||
// additional linker switches
|
// additional linker switches
|
||||||
for (unsigned i = 0; i < global.params.linkswitches->dim; i++)
|
for (unsigned i = 0; i < global.params.linkswitches->dim; i++)
|
||||||
{
|
{
|
||||||
char *p = static_cast<char *>(global.params.linkswitches->data[i]);
|
const char *p = static_cast<const char *>(global.params.linkswitches->data[i]);
|
||||||
// Don't push -l and -L switches using -Xlinker, but pass them directly
|
// Don't push -l and -L switches using -Xlinker, but pass them directly
|
||||||
// to GCC. This makes sure user-defined paths take precedence over
|
// to GCC. This makes sure user-defined paths take precedence over
|
||||||
// GCC's builtin LIBRARY_PATHs.
|
// GCC's builtin LIBRARY_PATHs.
|
||||||
@@ -279,14 +279,14 @@ static int linkObjToBinaryWin(bool sharedLib)
|
|||||||
// object files
|
// object files
|
||||||
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
||||||
{
|
{
|
||||||
char *p = static_cast<char *>(global.params.objfiles->data[i]);
|
const char *p = static_cast<const char *>(global.params.objfiles->data[i]);
|
||||||
args.push_back(p);
|
args.push_back(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// user libs
|
// user libs
|
||||||
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
|
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
|
||||||
{
|
{
|
||||||
char *p = static_cast<char *>(global.params.libfiles->data[i]);
|
const char *p = static_cast<const char *>(global.params.libfiles->data[i]);
|
||||||
args.push_back(p);
|
args.push_back(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ static int linkObjToBinaryWin(bool sharedLib)
|
|||||||
{
|
{
|
||||||
static const std::string LIBPATH("-L");
|
static const std::string LIBPATH("-L");
|
||||||
static const std::string LIB("-l");
|
static const std::string LIB("-l");
|
||||||
std::string str(static_cast<char *>(global.params.linkswitches->data[i]));
|
std::string str(static_cast<const char *>(global.params.linkswitches->data[i]));
|
||||||
if (str.length() > 2)
|
if (str.length() > 2)
|
||||||
{
|
{
|
||||||
if (std::equal(LIBPATH.begin(), LIBPATH.end(), str.begin()))
|
if (std::equal(LIBPATH.begin(), LIBPATH.end(), str.begin()))
|
||||||
@@ -386,7 +386,7 @@ void createStaticLibrary()
|
|||||||
if (Module::rootModule)
|
if (Module::rootModule)
|
||||||
libName = Module::rootModule->toChars();
|
libName = Module::rootModule->toChars();
|
||||||
else if (global.params.objfiles->dim)
|
else if (global.params.objfiles->dim)
|
||||||
libName = FileName::removeExt(static_cast<char*>(global.params.objfiles->data[0]));
|
libName = FileName::removeExt(static_cast<const char*>(global.params.objfiles->data[0]));
|
||||||
else
|
else
|
||||||
libName = "a.out";
|
libName = "a.out";
|
||||||
}
|
}
|
||||||
@@ -406,7 +406,7 @@ void createStaticLibrary()
|
|||||||
// object files
|
// object files
|
||||||
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
||||||
{
|
{
|
||||||
char *p = static_cast<char *>(global.params.objfiles->data[i]);
|
const char *p = static_cast<const char *>(global.params.objfiles->data[i]);
|
||||||
args.push_back(p);
|
args.push_back(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-18
@@ -139,7 +139,7 @@ static void processVersions(std::vector<std::string>& list, const char* type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to handle -of, -od, etc.
|
// Helper function to handle -of, -od, etc.
|
||||||
static void initFromString(char*& dest, const cl::opt<std::string>& src) {
|
static void initFromString(const char*& dest, const cl::opt<std::string>& src) {
|
||||||
dest = 0;
|
dest = 0;
|
||||||
if (src.getNumOccurrences() != 0) {
|
if (src.getNumOccurrences() != 0) {
|
||||||
if (src.empty())
|
if (src.empty())
|
||||||
@@ -370,7 +370,7 @@ static void parseCommandLine(int argc, char **argv, Strings &sourceFiles, bool &
|
|||||||
{
|
{
|
||||||
for (unsigned i = 0; i < libs->dim; i++)
|
for (unsigned i = 0; i < libs->dim; i++)
|
||||||
{
|
{
|
||||||
char* lib = static_cast<char *>(libs->data[i]);
|
const char* lib = static_cast<const char *>(libs->data[i]);
|
||||||
char *arg = static_cast<char *>(mem.malloc(strlen(lib) + 3));
|
char *arg = static_cast<char *>(mem.malloc(strlen(lib) + 3));
|
||||||
strcpy(arg, "-l");
|
strcpy(arg, "-l");
|
||||||
strcpy(arg+2, lib);
|
strcpy(arg+2, lib);
|
||||||
@@ -720,9 +720,6 @@ void genCmain(Scope *sc)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
mem.init(); // initialize storage allocator
|
|
||||||
mem.setStackBottom(&argv);
|
|
||||||
|
|
||||||
// stack trace on signals
|
// stack trace on signals
|
||||||
llvm::sys::PrintStackTraceOnErrorSignal();
|
llvm::sys::PrintStackTraceOnErrorSignal();
|
||||||
|
|
||||||
@@ -818,7 +815,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
for (unsigned i = 0; i < global.params.imppath->dim; i++)
|
for (unsigned i = 0; i < global.params.imppath->dim; i++)
|
||||||
{
|
{
|
||||||
char *path = static_cast<char *>(global.params.imppath->data[i]);
|
const char *path = static_cast<const char *>(global.params.imppath->data[i]);
|
||||||
Strings *a = FileName::splitPath(path);
|
Strings *a = FileName::splitPath(path);
|
||||||
|
|
||||||
if (a)
|
if (a)
|
||||||
@@ -835,7 +832,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
for (unsigned i = 0; i < global.params.fileImppath->dim; i++)
|
for (unsigned i = 0; i < global.params.fileImppath->dim; i++)
|
||||||
{
|
{
|
||||||
char *path = static_cast<char *>(global.params.fileImppath->data[i]);
|
const char *path = static_cast<const char *>(global.params.fileImppath->data[i]);
|
||||||
Strings *a = FileName::splitPath(path);
|
Strings *a = FileName::splitPath(path);
|
||||||
|
|
||||||
if (a)
|
if (a)
|
||||||
@@ -861,7 +858,7 @@ int main(int argc, char **argv)
|
|||||||
const char *ext;
|
const char *ext;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
const char *p = static_cast<char *>(files.data[i]);
|
const char *p = static_cast<const char *>(files.data[i]);
|
||||||
|
|
||||||
p = FileName::name(p); // strip path
|
p = FileName::name(p); // strip path
|
||||||
ext = FileName::ext(p);
|
ext = FileName::ext(p);
|
||||||
@@ -876,7 +873,7 @@ int main(int argc, char **argv)
|
|||||||
Port::stricmp(ext, global.bc_ext) == 0)
|
Port::stricmp(ext, global.bc_ext) == 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
global.params.objfiles->push(static_cast<char *>(files.data[i]));
|
global.params.objfiles->push(static_cast<const char *>(files.data[i]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,39 +885,39 @@ int main(int argc, char **argv)
|
|||||||
if (Port::stricmp(ext, "lib") == 0)
|
if (Port::stricmp(ext, "lib") == 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
global.params.libfiles->push(static_cast<char *>(files.data[i]));
|
global.params.libfiles->push(static_cast<const char *>(files.data[i]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(ext, global.ddoc_ext) == 0)
|
if (strcmp(ext, global.ddoc_ext) == 0)
|
||||||
{
|
{
|
||||||
global.params.ddocfiles->push(static_cast<char *>(files.data[i]));
|
global.params.ddocfiles->push(static_cast<const char *>(files.data[i]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileName::equals(ext, global.json_ext))
|
if (FileName::equals(ext, global.json_ext))
|
||||||
{
|
{
|
||||||
global.params.doXGeneration = 1;
|
global.params.doXGeneration = 1;
|
||||||
global.params.xfilename = static_cast<char *>(files.data[i]);
|
global.params.xfilename = static_cast<const char *>(files.data[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !POSIX
|
#if !POSIX
|
||||||
if (Port::stricmp(ext, "res") == 0)
|
if (Port::stricmp(ext, "res") == 0)
|
||||||
{
|
{
|
||||||
global.params.resfile = static_cast<char *>(files.data[i]);
|
global.params.resfile = static_cast<const char *>(files.data[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Port::stricmp(ext, "def") == 0)
|
if (Port::stricmp(ext, "def") == 0)
|
||||||
{
|
{
|
||||||
global.params.deffile = static_cast<char *>(files.data[i]);
|
global.params.deffile = static_cast<const char *>(files.data[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Port::stricmp(ext, "exe") == 0)
|
if (Port::stricmp(ext, "exe") == 0)
|
||||||
{
|
{
|
||||||
global.params.exefile = static_cast<char *>(files.data[i]);
|
global.params.exefile = static_cast<const char *>(files.data[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -953,14 +950,14 @@ int main(int argc, char **argv)
|
|||||||
if (!*p)
|
if (!*p)
|
||||||
{
|
{
|
||||||
Linvalid:
|
Linvalid:
|
||||||
error("invalid file name '%s'", static_cast<char *>(files.data[i]));
|
error("invalid file name '%s'", static_cast<const char *>(files.data[i]));
|
||||||
fatal();
|
fatal();
|
||||||
}
|
}
|
||||||
name = p;
|
name = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = Lexer::idPool(name);
|
id = Lexer::idPool(name);
|
||||||
Module *m = new Module(static_cast<char *>(files.data[i]), id, global.params.doDocComments, global.params.doHdrGeneration);
|
Module *m = new Module(static_cast<const char *>(files.data[i]), id, global.params.doDocComments, global.params.doHdrGeneration);
|
||||||
modules.push(m);
|
modules.push(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1168,7 +1165,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
Module *m = modules[0];
|
Module *m = modules[0];
|
||||||
|
|
||||||
char* oname;
|
const char* oname;
|
||||||
const char* filename;
|
const char* filename;
|
||||||
if ((oname = global.params.exefile) || (oname = global.params.objname))
|
if ((oname = global.params.exefile) || (oname = global.params.objname))
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-2
@@ -17,10 +17,9 @@
|
|||||||
|
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
#include <string>
|
|
||||||
|
|
||||||
template <typename TYPE> struct Array;
|
template <typename TYPE> struct Array;
|
||||||
typedef Array<char> Strings;
|
typedef Array<const char> Strings;
|
||||||
|
|
||||||
namespace opts {
|
namespace opts {
|
||||||
namespace cl = llvm::cl;
|
namespace cl = llvm::cl;
|
||||||
|
|||||||
+1
-1
Submodule runtime/druntime updated: 70ad65608e...ef5258bd38
+1
-1
Submodule runtime/phobos updated: ea3097dc65...f0da179876
Reference in New Issue
Block a user