mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-10-10 11:07:01 +02:00
First merge of 2.064 beta.
This corresponds to DMD commit a913ce4bc59a94a022a27e390fc841f4aededffb. Doesn't build Phobos yet.
This commit is contained in:
committed by
Kai Nacke
parent
c400d180d2
commit
cb341586e3
+58
-18
@@ -38,14 +38,14 @@ int hasPackageAccess(Scope *sc, Dsymbol *s);
|
||||
* Return PROT access for Dsymbol smember in this declaration.
|
||||
*/
|
||||
|
||||
enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
|
||||
PROT AggregateDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
return PROTpublic;
|
||||
}
|
||||
|
||||
enum PROT StructDeclaration::getAccess(Dsymbol *smember)
|
||||
PROT StructDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
@@ -62,9 +62,9 @@ enum PROT StructDeclaration::getAccess(Dsymbol *smember)
|
||||
return access_ret;
|
||||
}
|
||||
|
||||
enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
|
||||
PROT ClassDeclaration::getAccess(Dsymbol *smember)
|
||||
{
|
||||
enum PROT access_ret = PROTnone;
|
||||
PROT access_ret = PROTnone;
|
||||
|
||||
#if LOG
|
||||
printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
|
||||
@@ -84,7 +84,7 @@ enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
|
||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||
{ BaseClass *b = (*baseclasses)[i];
|
||||
|
||||
enum PROT access = b->base->getAccess(smember);
|
||||
PROT access = b->base->getAccess(smember);
|
||||
switch (access)
|
||||
{
|
||||
case PROTnone:
|
||||
@@ -152,7 +152,7 @@ static int accessCheckX(
|
||||
{
|
||||
for (size_t i = 0; i < cdthis->baseclasses->dim; i++)
|
||||
{ BaseClass *b = (*cdthis->baseclasses)[i];
|
||||
enum PROT access = b->base->getAccess(smember);
|
||||
PROT access = b->base->getAccess(smember);
|
||||
if (access >= PROTprotected ||
|
||||
accessCheckX(smember, sfunc, b->base, cdscope)
|
||||
)
|
||||
@@ -192,7 +192,7 @@ void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
|
||||
|
||||
FuncDeclaration *f = sc->func;
|
||||
AggregateDeclaration *cdscope = sc->getStructClassScope();
|
||||
enum PROT access;
|
||||
PROT access;
|
||||
|
||||
#if LOG
|
||||
printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n",
|
||||
@@ -214,7 +214,7 @@ void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
|
||||
//assert(smember->parent->isBaseOf(this, NULL));
|
||||
|
||||
if (smemberparent == this)
|
||||
{ enum PROT access2 = smember->prot();
|
||||
{ PROT access2 = smember->prot();
|
||||
|
||||
result = access2 >= PROTpublic ||
|
||||
hasPrivateAccess(f) ||
|
||||
@@ -290,25 +290,60 @@ int hasPackageAccess(Scope *sc, Dsymbol *s)
|
||||
printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc);
|
||||
#endif
|
||||
|
||||
Package *pkg = NULL;
|
||||
for (; s; s = s->parent)
|
||||
{
|
||||
if (s->isPackage() && !s->isModule())
|
||||
if (Module *m = s->isModule())
|
||||
{
|
||||
DsymbolTable *dst = Package::resolve(m->md ? m->md->packages : NULL, NULL, NULL);
|
||||
assert(dst);
|
||||
Dsymbol *s2 = dst->lookup(m->ident);
|
||||
assert(s2);
|
||||
Package *p = s2->isPackage();
|
||||
if (p && p->isPkgMod == PKGmodule)
|
||||
{
|
||||
assert(p->mod == m);
|
||||
pkg = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((pkg = s->isPackage()) != NULL)
|
||||
break;
|
||||
}
|
||||
#if LOG
|
||||
if (s)
|
||||
printf("\tthis is in package '%s'\n", s->toChars());
|
||||
if (pkg)
|
||||
printf("\tthis is in package '%s'\n", pkg->toChars());
|
||||
#endif
|
||||
|
||||
if (s && s == sc->module->parent)
|
||||
if (pkg)
|
||||
{
|
||||
if (pkg == sc->module->parent)
|
||||
{
|
||||
#if LOG
|
||||
printf("\ts is in same package as sc\n");
|
||||
printf("\ts is in same package as sc\n");
|
||||
#endif
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
if (pkg->isPkgMod == PKGmodule && pkg->mod == sc->module)
|
||||
{
|
||||
#if LOG
|
||||
printf("\ts is in same package.d module as sc\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
s = sc->module->parent;
|
||||
for (; s; s = s->parent)
|
||||
{
|
||||
if (s == pkg)
|
||||
{
|
||||
#if LOG
|
||||
printf("\ts is in ancestor package of sc\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if LOG
|
||||
printf("\tno package access\n");
|
||||
#endif
|
||||
@@ -375,6 +410,9 @@ int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
|
||||
|
||||
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
|
||||
{
|
||||
if (sc->flags & SCOPEnoaccesscheck)
|
||||
return;
|
||||
|
||||
#if LOG
|
||||
if (e)
|
||||
{ printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars());
|
||||
@@ -395,7 +433,8 @@ void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
|
||||
}
|
||||
}
|
||||
else if (e->type->ty == Tclass)
|
||||
{ // Do access check
|
||||
{
|
||||
// Do access check
|
||||
ClassDeclaration *cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
|
||||
if (e->op == TOKsuper)
|
||||
{
|
||||
@@ -406,7 +445,8 @@ void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
else if (e->type->ty == Tstruct)
|
||||
{ // Do access check
|
||||
{
|
||||
// Do access check
|
||||
StructDeclaration *cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
|
||||
cd->accessCheck(loc, sc, d);
|
||||
}
|
||||
|
||||
+66
-32
@@ -20,19 +20,19 @@
|
||||
#include "dsymbol.h"
|
||||
#include "declaration.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct TypeFunction;
|
||||
struct Expression;
|
||||
struct FuncDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct DeleteDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct TypeInfoClassDeclaration;
|
||||
struct VarDeclaration;
|
||||
class Identifier;
|
||||
class Type;
|
||||
class TypeFunction;
|
||||
class Expression;
|
||||
class FuncDeclaration;
|
||||
class CtorDeclaration;
|
||||
class DtorDeclaration;
|
||||
class InvariantDeclaration;
|
||||
class NewDeclaration;
|
||||
class DeleteDeclaration;
|
||||
class InterfaceDeclaration;
|
||||
class TypeInfoClassDeclaration;
|
||||
class VarDeclaration;
|
||||
struct dt_t;
|
||||
|
||||
enum Sizeok
|
||||
@@ -42,17 +42,18 @@ enum Sizeok
|
||||
SIZEOKfwd, // error in computing size of aggregate
|
||||
};
|
||||
|
||||
struct AggregateDeclaration : ScopeDsymbol
|
||||
class AggregateDeclaration : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
Type *type;
|
||||
StorageClass storage_class;
|
||||
enum PROT protection;
|
||||
PROT protection;
|
||||
Type *handle; // 'this' type
|
||||
unsigned structsize; // size of struct
|
||||
unsigned alignsize; // size of struct for alignment purposes
|
||||
int hasUnions; // set if aggregate has overlapping fields
|
||||
VarDeclarations fields; // VarDeclaration fields
|
||||
enum Sizeok sizeok; // set when structsize contains valid data
|
||||
Sizeok sizeok; // set when structsize contains valid data
|
||||
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
|
||||
bool isdeprecated; // !=0 if deprecated
|
||||
|
||||
@@ -103,7 +104,8 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
FuncDeclaration *buildInv(Scope *sc);
|
||||
bool isNested();
|
||||
void makeNested();
|
||||
int isExport();
|
||||
bool isExport();
|
||||
void searchCtor();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toJson(JsonOut *json);
|
||||
@@ -120,7 +122,7 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
int hasPrivateAccess(Dsymbol *smember); // does smember have private access to members of this class?
|
||||
void accessCheck(Loc loc, Scope *sc, Dsymbol *smember);
|
||||
|
||||
enum PROT prot();
|
||||
PROT prot();
|
||||
|
||||
#if IN_DMD
|
||||
// Back end
|
||||
@@ -137,8 +139,18 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
#endif
|
||||
};
|
||||
|
||||
struct StructDeclaration : AggregateDeclaration
|
||||
struct StructFlags
|
||||
{
|
||||
typedef unsigned Type;
|
||||
enum Enum
|
||||
{
|
||||
hasPointers = 0x1, // NB: should use noPointers as in ClassFlags
|
||||
};
|
||||
};
|
||||
|
||||
class StructDeclaration : public AggregateDeclaration
|
||||
{
|
||||
public:
|
||||
int zeroInit; // !=0 if initialize with 0 fill
|
||||
#if DMDV2
|
||||
int hasIdentityAssign; // !=0 if has identity opAssign
|
||||
@@ -148,7 +160,9 @@ struct StructDeclaration : AggregateDeclaration
|
||||
FuncDeclaration *postblit; // aggregate postblit
|
||||
|
||||
FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals
|
||||
FuncDeclaration *xcmp; // TypeInfo_Struct.xopCmp
|
||||
static FuncDeclaration *xerreq; // object.xopEquals
|
||||
static FuncDeclaration *xerrcmp; // object.xopCmp
|
||||
|
||||
structalign_t alignment; // alignment applied outside of the struct
|
||||
#endif
|
||||
@@ -177,6 +191,7 @@ struct StructDeclaration : AggregateDeclaration
|
||||
FuncDeclaration *buildCpCtor(Scope *sc);
|
||||
FuncDeclaration *buildOpEquals(Scope *sc);
|
||||
FuncDeclaration *buildXopEquals(Scope *sc);
|
||||
FuncDeclaration *buildXopCmp(Scope *sc);
|
||||
#endif
|
||||
void toDocBuffer(OutBuffer *buf, Scope *sc);
|
||||
|
||||
@@ -195,8 +210,9 @@ struct StructDeclaration : AggregateDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct UnionDeclaration : StructDeclaration
|
||||
class UnionDeclaration : public StructDeclaration
|
||||
{
|
||||
public:
|
||||
UnionDeclaration(Loc loc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
const char *kind();
|
||||
@@ -207,10 +223,10 @@ struct UnionDeclaration : StructDeclaration
|
||||
struct BaseClass
|
||||
{
|
||||
Type *type; // (before semantic processing)
|
||||
enum PROT protection; // protection for the base interface
|
||||
PROT protection; // protection for the base interface
|
||||
|
||||
ClassDeclaration *base;
|
||||
int offset; // 'this' pointer offset
|
||||
unsigned offset; // 'this' pointer offset
|
||||
FuncDeclarations vtbl; // for interfaces: Array of FuncDeclaration's
|
||||
// making up the vtbl[]
|
||||
|
||||
@@ -219,7 +235,7 @@ struct BaseClass
|
||||
// are a copy of the InterfaceDeclaration::interfaces
|
||||
|
||||
BaseClass();
|
||||
BaseClass(Type *type, enum PROT protection);
|
||||
BaseClass(Type *type, PROT protection);
|
||||
|
||||
int fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance);
|
||||
void copyBaseInterfaces(BaseClasses *);
|
||||
@@ -233,10 +249,26 @@ struct BaseClass
|
||||
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size
|
||||
#endif
|
||||
|
||||
struct ClassDeclaration : AggregateDeclaration
|
||||
struct ClassFlags
|
||||
{
|
||||
typedef unsigned Type;
|
||||
enum Enum
|
||||
{
|
||||
isCOMclass = 0x1,
|
||||
noPointers = 0x2,
|
||||
hasOffTi = 0x4,
|
||||
hasCtor = 0x8,
|
||||
hasGetMembers = 0x10,
|
||||
hasTypeInfo = 0x20,
|
||||
isAbstract = 0x40,
|
||||
isCPPclass = 0x80,
|
||||
};
|
||||
};
|
||||
|
||||
class ClassDeclaration : public AggregateDeclaration
|
||||
{
|
||||
public:
|
||||
static ClassDeclaration *object;
|
||||
static ClassDeclaration *classinfo;
|
||||
static ClassDeclaration *throwable;
|
||||
static ClassDeclaration *exception;
|
||||
static ClassDeclaration *errorException;
|
||||
@@ -264,14 +296,17 @@ struct ClassDeclaration : AggregateDeclaration
|
||||
TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
|
||||
int com; // !=0 if this is a COM class (meaning
|
||||
// it derives from IUnknown)
|
||||
#if DMDV2
|
||||
int cpp; // !=0 if this is a C++ interface
|
||||
#endif
|
||||
int isscope; // !=0 if this is an auto class
|
||||
int isabstract; // !=0 if abstract class
|
||||
int inuse; // to prevent recursive attempts
|
||||
enum Semantic doAncestorsSemantic; // Before searching symbol, whole ancestors should finish
|
||||
Semantic doAncestorsSemantic; // Before searching symbol, whole ancestors should finish
|
||||
// calling semantic() at least once, due to fill symtab
|
||||
// and do addMember(). [== Semantic(Start,In,Done)]
|
||||
|
||||
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, bool inObject = false);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -291,9 +326,10 @@ struct ClassDeclaration : AggregateDeclaration
|
||||
int isCOMclass();
|
||||
virtual int isCOMinterface();
|
||||
#if DMDV2
|
||||
int isCPPclass();
|
||||
virtual int isCPPinterface();
|
||||
#endif
|
||||
int isAbstract();
|
||||
bool isAbstract();
|
||||
virtual int vtblOffset();
|
||||
const char *kind();
|
||||
const char *mangle(bool isv = false);
|
||||
@@ -323,11 +359,9 @@ struct ClassDeclaration : AggregateDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct InterfaceDeclaration : ClassDeclaration
|
||||
class InterfaceDeclaration : public ClassDeclaration
|
||||
{
|
||||
#if DMDV2
|
||||
int cpp; // !=0 if this is a C++ interface
|
||||
#endif
|
||||
public:
|
||||
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
|
||||
+2
-1
@@ -22,8 +22,9 @@
|
||||
|
||||
#if DMDV2
|
||||
|
||||
struct AliasThis : Dsymbol
|
||||
class AliasThis : public Dsymbol
|
||||
{
|
||||
public:
|
||||
// alias Identifier this;
|
||||
Identifier *ident;
|
||||
|
||||
|
||||
+18
-20
@@ -26,9 +26,7 @@
|
||||
* Creating an iterator for this would be much more complex.
|
||||
*/
|
||||
|
||||
typedef int (*fp_t)(Expression *, void *);
|
||||
|
||||
int Expression::apply(fp_t fp, void *param)
|
||||
int Expression::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return (*fp)(this, param);
|
||||
}
|
||||
@@ -38,7 +36,7 @@ int Expression::apply(fp_t fp, void *param)
|
||||
*/
|
||||
#define condApply(t, fp, param) (t ? t->apply(fp, param) : 0)
|
||||
|
||||
int NewExp::apply(int (*fp)(Expression *, void *), void *param)
|
||||
int NewExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
//printf("NewExp::apply(): %s\n", toChars());
|
||||
|
||||
@@ -48,7 +46,7 @@ int NewExp::apply(int (*fp)(Expression *, void *), void *param)
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
int NewAnonClassExp::apply(int (*fp)(Expression *, void *), void *param)
|
||||
int NewAnonClassExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
//printf("NewAnonClassExp::apply(): %s\n", toChars());
|
||||
|
||||
@@ -58,47 +56,47 @@ int NewAnonClassExp::apply(int (*fp)(Expression *, void *), void *param)
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
int UnaExp::apply(fp_t fp, void *param)
|
||||
int UnaExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return e1->apply(fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
int BinExp::apply(fp_t fp, void *param)
|
||||
int BinExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return e1->apply(fp, param) ||
|
||||
e2->apply(fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
int AssertExp::apply(fp_t fp, void *param)
|
||||
int AssertExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
|
||||
//printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
|
||||
return e1->apply(fp, param) ||
|
||||
condApply(msg, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int CallExp::apply(fp_t fp, void *param)
|
||||
int CallExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
|
||||
//printf("CallExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
|
||||
return e1->apply(fp, param) ||
|
||||
condApply(arguments, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int ArrayExp::apply(fp_t fp, void *param)
|
||||
int ArrayExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
//printf("ArrayExp::apply(fp_t fp, void *param): %s\n", toChars());
|
||||
//printf("ArrayExp::apply(apply_fp_t fp, void *param): %s\n", toChars());
|
||||
return e1->apply(fp, param) ||
|
||||
condApply(arguments, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int SliceExp::apply(fp_t fp, void *param)
|
||||
int SliceExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return e1->apply(fp, param) ||
|
||||
condApply(lwr, fp, param) ||
|
||||
@@ -107,14 +105,14 @@ int SliceExp::apply(fp_t fp, void *param)
|
||||
}
|
||||
|
||||
|
||||
int ArrayLiteralExp::apply(fp_t fp, void *param)
|
||||
int ArrayLiteralExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return condApply(elements, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
}
|
||||
|
||||
|
||||
int AssocArrayLiteralExp::apply(fp_t fp, void *param)
|
||||
int AssocArrayLiteralExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return condApply(keys, fp, param) ||
|
||||
condApply(values, fp, param) ||
|
||||
@@ -122,19 +120,19 @@ int AssocArrayLiteralExp::apply(fp_t fp, void *param)
|
||||
}
|
||||
|
||||
|
||||
int StructLiteralExp::apply(fp_t fp, void *param)
|
||||
int StructLiteralExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
if(stageflags & stageApply) return 0;
|
||||
int old = stageflags;
|
||||
stageflags |= stageApply;
|
||||
int ret = condApply(elements, fp, param) ||
|
||||
(*fp)(this, param);
|
||||
stageflags = old;
|
||||
stageflags = old;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int TupleExp::apply(fp_t fp, void *param)
|
||||
int TupleExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return (e0 ? (*fp)(e0, param) : 0) ||
|
||||
condApply(exps, fp, param) ||
|
||||
@@ -142,7 +140,7 @@ int TupleExp::apply(fp_t fp, void *param)
|
||||
}
|
||||
|
||||
|
||||
int CondExp::apply(fp_t fp, void *param)
|
||||
int CondExp::apply(apply_fp_t fp, void *param)
|
||||
{
|
||||
return econd->apply(fp, param) ||
|
||||
e1->apply(fp, param) ||
|
||||
|
||||
+32
-18
@@ -154,14 +154,6 @@ TypeTuple *TypeSArray::toArgTypes()
|
||||
#endif
|
||||
}
|
||||
|
||||
TypeTuple *TypeDArray::toArgTypes()
|
||||
{
|
||||
/* Should be done as if it were:
|
||||
* struct S { size_t length; void* ptr; }
|
||||
*/
|
||||
return new TypeTuple(Type::tsize_t, Type::tvoidptr);
|
||||
}
|
||||
|
||||
TypeTuple *TypeAArray::toArgTypes()
|
||||
{
|
||||
return new TypeTuple(Type::tvoidptr);
|
||||
@@ -172,14 +164,6 @@ TypeTuple *TypePointer::toArgTypes()
|
||||
return new TypeTuple(Type::tvoidptr);
|
||||
}
|
||||
|
||||
TypeTuple *TypeDelegate::toArgTypes()
|
||||
{
|
||||
/* Should be done as if it were:
|
||||
* struct S { void* ptr; void* funcptr; }
|
||||
*/
|
||||
return new TypeTuple(Type::tvoidptr, Type::tvoidptr);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* Convert a floating point type into the equivalent integral type.
|
||||
*/
|
||||
@@ -273,6 +257,38 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2)
|
||||
return t;
|
||||
}
|
||||
|
||||
TypeTuple *TypeDArray::toArgTypes()
|
||||
{
|
||||
/* Should be done as if it were:
|
||||
* struct S { size_t length; void* ptr; }
|
||||
*/
|
||||
if (global.params.is64bit && !global.params.isLP64)
|
||||
{
|
||||
// For AMD64 ILP32 ABI, D arrays fit into a single integer register.
|
||||
unsigned offset = Type::tsize_t->size(Loc());
|
||||
Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
|
||||
if (t)
|
||||
return new TypeTuple(t);
|
||||
}
|
||||
return new TypeTuple(Type::tsize_t, Type::tvoidptr);
|
||||
}
|
||||
|
||||
TypeTuple *TypeDelegate::toArgTypes()
|
||||
{
|
||||
/* Should be done as if it were:
|
||||
* struct S { size_t length; void* ptr; }
|
||||
*/
|
||||
if (global.params.is64bit && !global.params.isLP64)
|
||||
{
|
||||
// For AMD64 ILP32 ABI, delegates fit into a single integer register.
|
||||
unsigned offset = Type::tsize_t->size(Loc());
|
||||
Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
|
||||
if (t)
|
||||
return new TypeTuple(t);
|
||||
}
|
||||
return new TypeTuple(Type::tvoidptr, Type::tvoidptr);
|
||||
}
|
||||
|
||||
TypeTuple *TypeStruct::toArgTypes()
|
||||
{
|
||||
//printf("TypeStruct::toArgTypes() %s\n", toChars());
|
||||
@@ -309,8 +325,6 @@ TypeTuple *TypeStruct::toArgTypes()
|
||||
if (global.params.is64bit && sym->fields.dim)
|
||||
{
|
||||
#if 1
|
||||
unsigned sz1 = 0;
|
||||
unsigned sz2 = 0;
|
||||
t1 = NULL;
|
||||
for (size_t i = 0; i < sym->fields.dim; i++)
|
||||
{ VarDeclaration *f = sym->fields[i];
|
||||
|
||||
+142
-100
@@ -250,18 +250,18 @@ int isDruntimeArrayOp(Identifier *ident)
|
||||
|
||||
ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
|
||||
{
|
||||
ArrayOp *op = new ArrayOp;
|
||||
#if IN_LLVM // LDC: Build parameters.
|
||||
Parameters *fparams = new Parameters();
|
||||
Expression *loopbody = exp->buildArrayLoop(fparams);
|
||||
|
||||
ArrayOp *op = new ArrayOp;
|
||||
if (isDruntimeArrayOp(ident))
|
||||
#if IN_LLVM
|
||||
{
|
||||
#endif
|
||||
op->cFunc = FuncDeclaration::genCfunc(fparams, exp->type, ident);
|
||||
#if IN_LLVM
|
||||
op->cFunc->isArrayOp = 2;
|
||||
}
|
||||
#else
|
||||
if (isDruntimeArrayOp(ident))
|
||||
op->cFunc = FuncDeclaration::genCfunc(exp->type, ident);
|
||||
#endif
|
||||
else
|
||||
op->cFunc = NULL;
|
||||
@@ -271,10 +271,6 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
|
||||
* loopbody;
|
||||
* return p;
|
||||
*/
|
||||
#if !IN_LLVM
|
||||
Parameters *fparams = new Parameters();
|
||||
Expression *loopbody = exp->buildArrayLoop(fparams);
|
||||
#endif
|
||||
Parameter *p = (*fparams)[0 /*fparams->dim - 1*/];
|
||||
#if DMDV1
|
||||
// for (size_t i = 0; i < p.length; i++)
|
||||
@@ -298,9 +294,12 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
|
||||
//printf("s2: %s\n", s2->toChars());
|
||||
Statement *fbody = new CompoundStatement(Loc(), s1, s2);
|
||||
|
||||
// Built-in array ops should be @trusted, pure and nothrow
|
||||
StorageClass stc = STCtrusted | STCpure | STCnothrow;
|
||||
|
||||
/* Construct the function
|
||||
*/
|
||||
TypeFunction *ftype = new TypeFunction(fparams, exp->type, 0, LINKc);
|
||||
TypeFunction *ftype = new TypeFunction(fparams, exp->type, 0, LINKc, stc);
|
||||
//printf("ftype: %s\n", ftype->toChars());
|
||||
FuncDeclaration *fd = new FuncDeclaration(Loc(), Loc(), ident, STCundefined, ftype);
|
||||
fd->fbody = fbody;
|
||||
@@ -336,6 +335,13 @@ bool isArrayOpValid(Expression *e)
|
||||
{
|
||||
if (e->op == TOKslice)
|
||||
return true;
|
||||
if (e->op == TOKarrayliteral)
|
||||
{
|
||||
Type *t = e->type->toBasetype();
|
||||
while (t->ty == Tarray || t->ty == Tsarray)
|
||||
t = t->nextOf()->toBasetype();
|
||||
return (t->ty != Tvoid);
|
||||
}
|
||||
Type *tb = e->type->toBasetype();
|
||||
|
||||
if ( (tb->ty == Tarray) || (tb->ty == Tsarray) )
|
||||
@@ -482,6 +488,12 @@ void CastExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
Expression::buildArrayIdent(buf, arguments);
|
||||
}
|
||||
|
||||
void ArrayLiteralExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
buf->writestring("Slice");
|
||||
arguments->shift(this);
|
||||
}
|
||||
|
||||
void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
buf->writestring("Slice");
|
||||
@@ -497,30 +509,30 @@ void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
buf->writestring("Assign");
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
|
||||
{ \
|
||||
/* Evaluate assign expressions right to left \
|
||||
*/ \
|
||||
e2->buildArrayIdent(buf, arguments); \
|
||||
e1->buildArrayIdent(buf, arguments); \
|
||||
buf->writestring(#Str); \
|
||||
buf->writestring("ass"); \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
void BinAssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
/* Evaluate assign expressions right to left
|
||||
*/
|
||||
e2->buildArrayIdent(buf, arguments);
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
const char *s;
|
||||
switch(op)
|
||||
{
|
||||
case TOKaddass: s = "Addass"; break;
|
||||
case TOKminass: s = "Subass"; break;
|
||||
case TOKmulass: s = "Mulass"; break;
|
||||
case TOKdivass: s = "Divass"; break;
|
||||
case TOKmodass: s = "Modass"; break;
|
||||
case TOKxorass: s = "Xorass"; break;
|
||||
case TOKandass: s = "Andass"; break;
|
||||
case TOKorass: s = "Orass"; break;
|
||||
#if DMDV2
|
||||
X(Pow)
|
||||
case TOKpowass: s = "Powass"; break;
|
||||
#endif
|
||||
|
||||
#undef X
|
||||
default: assert(0);
|
||||
}
|
||||
buf->writestring(s);
|
||||
}
|
||||
|
||||
void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
@@ -534,29 +546,35 @@ void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
buf->writestring("Com");
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
|
||||
{ \
|
||||
/* Evaluate assign expressions left to right \
|
||||
*/ \
|
||||
e1->buildArrayIdent(buf, arguments); \
|
||||
e2->buildArrayIdent(buf, arguments); \
|
||||
buf->writestring(#Str); \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
void BinExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
|
||||
{
|
||||
/* Evaluate assign expressions left to right
|
||||
*/
|
||||
const char *s = NULL;
|
||||
switch(op)
|
||||
{
|
||||
case TOKadd: s = "Add"; break;
|
||||
case TOKmin: s = "Sub"; break;
|
||||
case TOKmul: s = "Mul"; break;
|
||||
case TOKdiv: s = "Div"; break;
|
||||
case TOKmod: s = "Mod"; break;
|
||||
case TOKxor: s = "Xor"; break;
|
||||
case TOKand: s = "And"; break;
|
||||
case TOKor: s = "Or"; break;
|
||||
#if DMDV2
|
||||
X(Pow)
|
||||
case TOKpow: s = "Pow"; break;
|
||||
#endif
|
||||
|
||||
#undef X
|
||||
default: break;
|
||||
}
|
||||
if (s)
|
||||
{
|
||||
e1->buildArrayIdent(buf, arguments);
|
||||
e2->buildArrayIdent(buf, arguments);
|
||||
buf->writestring(s);
|
||||
}
|
||||
else
|
||||
Expression::buildArrayIdent(buf, arguments);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Construct the inner loop for the array operation function,
|
||||
@@ -583,6 +601,19 @@ Expression *CastExp::buildArrayLoop(Parameters *fparams)
|
||||
return Expression::buildArrayLoop(fparams);
|
||||
}
|
||||
|
||||
Expression *ArrayLiteralExp::buildArrayLoop(Parameters *fparams)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("p", fparams->dim);
|
||||
Parameter *param = new Parameter(STCconst, type, id, NULL);
|
||||
fparams->shift(param);
|
||||
Expression *e = new IdentifierExp(Loc(), id);
|
||||
Expressions *arguments = new Expressions();
|
||||
Expression *index = new IdentifierExp(Loc(), Id::p);
|
||||
arguments->push(index);
|
||||
e = new ArrayExp(Loc(), e, arguments);
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *SliceExp::buildArrayLoop(Parameters *fparams)
|
||||
{
|
||||
Identifier *id = Identifier::generateId("p", fparams->dim);
|
||||
@@ -616,32 +647,33 @@ Expression *AssignExp::buildArrayLoop(Parameters *fparams)
|
||||
return e;
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
Expression *Str##AssignExp::buildArrayLoop(Parameters *fparams) \
|
||||
{ \
|
||||
/* Evaluate assign expressions right to left \
|
||||
*/ \
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams); \
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams); \
|
||||
Parameter *param = (*fparams)[0]; \
|
||||
param->storageClass = 0; \
|
||||
Expression *e = new Str##AssignExp(loc, ex1, ex2); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
Expression *BinAssignExp::buildArrayLoop(Parameters *fparams)
|
||||
{
|
||||
/* Evaluate assign expressions right to left
|
||||
*/
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams);
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams);
|
||||
Parameter *param = (*fparams)[0];
|
||||
param->storageClass = 0;
|
||||
Expression *e;
|
||||
switch(op)
|
||||
{
|
||||
case TOKaddass: return new AddAssignExp(loc, ex1, ex2);
|
||||
case TOKminass: return new MinAssignExp(loc, ex1, ex2);
|
||||
case TOKmulass: return new MulAssignExp(loc, ex1, ex2);
|
||||
case TOKdivass: return new DivAssignExp(loc, ex1, ex2);
|
||||
case TOKmodass: return new ModAssignExp(loc, ex1, ex2);
|
||||
case TOKxorass: return new XorAssignExp(loc, ex1, ex2);
|
||||
case TOKandass: return new AndAssignExp(loc, ex1, ex2);
|
||||
case TOKorass: return new OrAssignExp(loc, ex1, ex2);
|
||||
#if DMDV2
|
||||
X(Pow)
|
||||
case TOKpowass: return new PowAssignExp(loc, ex1, ex2);
|
||||
#endif
|
||||
|
||||
#undef X
|
||||
default:
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Expression *NegExp::buildArrayLoop(Parameters *fparams)
|
||||
{
|
||||
@@ -657,31 +689,34 @@ Expression *ComExp::buildArrayLoop(Parameters *fparams)
|
||||
return e;
|
||||
}
|
||||
|
||||
#define X(Str) \
|
||||
Expression *Str##Exp::buildArrayLoop(Parameters *fparams) \
|
||||
{ \
|
||||
/* Evaluate assign expressions left to right \
|
||||
*/ \
|
||||
Expression *ex1 = e1->buildArrayLoop(fparams); \
|
||||
Expression *ex2 = e2->buildArrayLoop(fparams); \
|
||||
Expression *e = new Str##Exp(Loc(), ex1, ex2); \
|
||||
return e; \
|
||||
}
|
||||
|
||||
X(Add)
|
||||
X(Min)
|
||||
X(Mul)
|
||||
X(Div)
|
||||
X(Mod)
|
||||
X(Xor)
|
||||
X(And)
|
||||
X(Or)
|
||||
Expression *BinExp::buildArrayLoop(Parameters *fparams)
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
case TOKadd:
|
||||
case TOKmin:
|
||||
case TOKmul:
|
||||
case TOKdiv:
|
||||
case TOKmod:
|
||||
case TOKxor:
|
||||
case TOKand:
|
||||
case TOKor:
|
||||
#if DMDV2
|
||||
X(Pow)
|
||||
case TOKpow:
|
||||
#endif
|
||||
|
||||
#undef X
|
||||
|
||||
{
|
||||
/* Evaluate assign expressions left to right
|
||||
*/
|
||||
BinExp *e = (BinExp *)copy();
|
||||
e->e1 = e->e1->buildArrayLoop(fparams);
|
||||
e->e2 = e->e2->buildArrayLoop(fparams);
|
||||
e->type = NULL;
|
||||
return e;
|
||||
}
|
||||
default:
|
||||
return Expression::buildArrayLoop(fparams);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Test if operand is a valid array op operand.
|
||||
@@ -692,6 +727,13 @@ int Expression::isArrayOperand()
|
||||
//printf("Expression::isArrayOperand() %s\n", toChars());
|
||||
if (op == TOKslice)
|
||||
return 1;
|
||||
if (op == TOKarrayliteral)
|
||||
{
|
||||
Type *t = type->toBasetype();
|
||||
while (t->ty == Tarray || t->ty == Tsarray)
|
||||
t = t->nextOf()->toBasetype();
|
||||
return (t->ty != Tvoid);
|
||||
}
|
||||
if (type->toBasetype()->ty == Tarray)
|
||||
{
|
||||
switch (op)
|
||||
|
||||
+30
-30
@@ -18,63 +18,63 @@
|
||||
|
||||
#include "root.h"
|
||||
|
||||
typedef ArrayBase<struct TemplateParameter> TemplateParameters;
|
||||
typedef Array<class TemplateParameter> TemplateParameters;
|
||||
|
||||
typedef ArrayBase<struct Expression> Expressions;
|
||||
typedef Array<class Expression> Expressions;
|
||||
|
||||
typedef ArrayBase<struct Statement> Statements;
|
||||
typedef Array<class Statement> Statements;
|
||||
|
||||
typedef ArrayBase<struct BaseClass> BaseClasses;
|
||||
typedef Array<class BaseClass> BaseClasses;
|
||||
|
||||
typedef ArrayBase<struct ClassDeclaration> ClassDeclarations;
|
||||
typedef Array<class ClassDeclaration> ClassDeclarations;
|
||||
|
||||
typedef ArrayBase<struct Dsymbol> Dsymbols;
|
||||
typedef Array<class Dsymbol> Dsymbols;
|
||||
|
||||
typedef ArrayBase<struct Object> Objects;
|
||||
typedef Array<class RootObject> Objects;
|
||||
|
||||
typedef ArrayBase<struct FuncDeclaration> FuncDeclarations;
|
||||
typedef Array<class FuncDeclaration> FuncDeclarations;
|
||||
|
||||
typedef ArrayBase<struct Parameter> Parameters;
|
||||
typedef Array<class Parameter> Parameters;
|
||||
|
||||
typedef ArrayBase<struct Identifier> Identifiers;
|
||||
typedef Array<class Identifier> Identifiers;
|
||||
|
||||
typedef ArrayBase<struct Initializer> Initializers;
|
||||
typedef Array<class Initializer> Initializers;
|
||||
|
||||
typedef ArrayBase<struct VarDeclaration> VarDeclarations;
|
||||
typedef Array<class VarDeclaration> VarDeclarations;
|
||||
|
||||
typedef ArrayBase<struct Type> Types;
|
||||
typedef Array<class Type> Types;
|
||||
|
||||
typedef ArrayBase<struct ScopeDsymbol> ScopeDsymbols;
|
||||
typedef Array<class ScopeDsymbol> ScopeDsymbols;
|
||||
|
||||
typedef ArrayBase<struct Catch> Catches;
|
||||
typedef Array<class Catch> Catches;
|
||||
|
||||
typedef ArrayBase<struct StaticDtorDeclaration> StaticDtorDeclarations;
|
||||
typedef Array<class StaticDtorDeclaration> StaticDtorDeclarations;
|
||||
|
||||
typedef ArrayBase<struct SharedStaticDtorDeclaration> SharedStaticDtorDeclarations;
|
||||
typedef Array<class SharedStaticDtorDeclaration> SharedStaticDtorDeclarations;
|
||||
|
||||
typedef ArrayBase<struct AliasDeclaration> AliasDeclarations;
|
||||
typedef Array<class AliasDeclaration> AliasDeclarations;
|
||||
|
||||
typedef ArrayBase<struct Module> Modules;
|
||||
typedef Array<class Module> Modules;
|
||||
|
||||
typedef ArrayBase<struct File> Files;
|
||||
typedef Array<class File> Files;
|
||||
|
||||
typedef ArrayBase<struct CaseStatement> CaseStatements;
|
||||
typedef Array<class CaseStatement> CaseStatements;
|
||||
|
||||
typedef ArrayBase<struct CompoundStatement> CompoundStatements;
|
||||
typedef Array<class CompoundStatement> CompoundStatements;
|
||||
|
||||
typedef ArrayBase<struct GotoCaseStatement> GotoCaseStatements;
|
||||
typedef Array<class GotoCaseStatement> GotoCaseStatements;
|
||||
|
||||
typedef ArrayBase<struct ReturnStatement> ReturnStatements;
|
||||
typedef Array<class ReturnStatement> ReturnStatements;
|
||||
|
||||
typedef ArrayBase<struct TemplateInstance> TemplateInstances;
|
||||
typedef Array<class TemplateInstance> TemplateInstances;
|
||||
|
||||
//typedef ArrayBase<char> Strings;
|
||||
//typedef Array<char> Strings;
|
||||
|
||||
typedef ArrayBase<void> Voids;
|
||||
typedef Array<void> Voids;
|
||||
|
||||
typedef ArrayBase<struct block> Blocks;
|
||||
typedef Array<struct block> Blocks;
|
||||
|
||||
typedef ArrayBase<struct Symbol> Symbols;
|
||||
typedef Array<struct Symbol> Symbols;
|
||||
|
||||
typedef ArrayBase<struct dt_t> Dts;
|
||||
typedef Array<struct dt_t> Dts;
|
||||
#endif
|
||||
|
||||
+127
-48
@@ -28,6 +28,7 @@
|
||||
#include "parse.h"
|
||||
#include "template.h"
|
||||
#include "hdrgen.h"
|
||||
#include "utf.h"
|
||||
#if IN_LLVM
|
||||
#include "../gen/pragma.h"
|
||||
#endif
|
||||
@@ -81,7 +82,7 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
}
|
||||
|
||||
void AttribDeclaration::setScopeNewSc(Scope *sc,
|
||||
StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection,
|
||||
StorageClass stc, LINK linkage, PROT protection, int explicitProtection,
|
||||
structalign_t structalign)
|
||||
{
|
||||
if (decl)
|
||||
@@ -116,7 +117,7 @@ void AttribDeclaration::setScopeNewSc(Scope *sc,
|
||||
}
|
||||
|
||||
void AttribDeclaration::semanticNewSc(Scope *sc,
|
||||
StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection,
|
||||
StorageClass stc, LINK linkage, PROT protection, int explicitProtection,
|
||||
structalign_t structalign)
|
||||
{
|
||||
if (decl)
|
||||
@@ -206,7 +207,7 @@ void AttribDeclaration::inlineScan()
|
||||
}
|
||||
}
|
||||
|
||||
void AttribDeclaration::addComment(unsigned char *comment)
|
||||
void AttribDeclaration::addComment(utf8_t *comment)
|
||||
{
|
||||
//printf("AttribDeclaration::addComment %s\n", comment);
|
||||
if (comment)
|
||||
@@ -261,7 +262,7 @@ void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffs
|
||||
}
|
||||
}
|
||||
|
||||
int AttribDeclaration::hasPointers()
|
||||
bool AttribDeclaration::hasPointers()
|
||||
{
|
||||
Dsymbols *d = include(NULL, NULL);
|
||||
|
||||
@@ -271,10 +272,10 @@ int AttribDeclaration::hasPointers()
|
||||
{
|
||||
Dsymbol *s = (*d)[i];
|
||||
if (s->hasPointers())
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AttribDeclaration::hasStaticCtorOrDtor()
|
||||
@@ -298,7 +299,7 @@ const char *AttribDeclaration::kind()
|
||||
return "attribute";
|
||||
}
|
||||
|
||||
int AttribDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
bool AttribDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
Dsymbols *d = include(NULL, NULL);
|
||||
|
||||
@@ -384,10 +385,10 @@ Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
|
||||
return scd;
|
||||
}
|
||||
|
||||
int StorageClassDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
bool StorageClassDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
|
||||
int t = Dsymbol::oneMembers(decl, ps, ident);
|
||||
bool t = Dsymbol::oneMembers(decl, ps, ident);
|
||||
if (t && *ps)
|
||||
{
|
||||
/* This is to deal with the following case:
|
||||
@@ -476,8 +477,8 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
|
||||
struct SCstring
|
||||
{
|
||||
StorageClass stc;
|
||||
enum TOK tok;
|
||||
Identifier *id;
|
||||
TOK tok;
|
||||
const char *id;
|
||||
};
|
||||
|
||||
static SCstring table[] =
|
||||
@@ -505,11 +506,11 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
|
||||
{ STCref, TOKref },
|
||||
{ STCtls },
|
||||
{ STCgshared, TOKgshared },
|
||||
{ STCproperty, TOKat, Id::property },
|
||||
{ STCsafe, TOKat, Id::safe },
|
||||
{ STCtrusted, TOKat, Id::trusted },
|
||||
{ STCsystem, TOKat, Id::system },
|
||||
{ STCdisable, TOKat, Id::disable },
|
||||
{ STCproperty, TOKat, "property" },
|
||||
{ STCsafe, TOKat, "safe" },
|
||||
{ STCtrusted, TOKat, "trusted" },
|
||||
{ STCsystem, TOKat, "system" },
|
||||
{ STCdisable, TOKat, "disable" },
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -523,12 +524,12 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
|
||||
if (tbl == STCtls) // TOKtls was removed
|
||||
return "__thread";
|
||||
|
||||
enum TOK tok = table[i].tok;
|
||||
TOK tok = table[i].tok;
|
||||
#if DMDV2
|
||||
if (tok == TOKat)
|
||||
{
|
||||
tmp[0] = '@';
|
||||
strcpy(tmp + 1, table[i].id->toChars());
|
||||
strcpy(tmp + 1, table[i].id);
|
||||
return tmp;
|
||||
}
|
||||
else
|
||||
@@ -599,7 +600,7 @@ void DeprecatedDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
|
||||
/********************************* LinkDeclaration ****************************/
|
||||
|
||||
LinkDeclaration::LinkDeclaration(enum LINK p, Dsymbols *decl)
|
||||
LinkDeclaration::LinkDeclaration(LINK p, Dsymbols *decl)
|
||||
: AttribDeclaration(decl)
|
||||
{
|
||||
//printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
|
||||
@@ -637,7 +638,7 @@ void LinkDeclaration::semantic3(Scope *sc)
|
||||
{
|
||||
//printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
|
||||
if (decl)
|
||||
{ enum LINK linkage_save = sc->linkage;
|
||||
{ LINK linkage_save = sc->linkage;
|
||||
|
||||
sc->linkage = linkage;
|
||||
for (size_t i = 0; i < decl->dim; i++)
|
||||
@@ -685,7 +686,7 @@ char *LinkDeclaration::toChars()
|
||||
|
||||
/********************************* ProtDeclaration ****************************/
|
||||
|
||||
ProtDeclaration::ProtDeclaration(enum PROT p, Dsymbols *decl)
|
||||
ProtDeclaration::ProtDeclaration(PROT p, Dsymbols *decl)
|
||||
: AttribDeclaration(decl)
|
||||
{
|
||||
protection = p;
|
||||
@@ -740,7 +741,7 @@ void ProtDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection)
|
||||
void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, PROT protection)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
@@ -805,7 +806,7 @@ void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
|
||||
/********************************* AnonDeclaration ****************************/
|
||||
|
||||
AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl)
|
||||
AnonDeclaration::AnonDeclaration(Loc loc, bool isunion, Dsymbols *decl)
|
||||
: AttribDeclaration(decl)
|
||||
{
|
||||
this->loc = loc;
|
||||
@@ -1012,10 +1013,13 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
Expression *e = (*args)[i];
|
||||
|
||||
e = e->ctfeSemantic(sc);
|
||||
sc = sc->startCTFE();
|
||||
e = e->semantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
if (e->op != TOKerror && e->op != TOKtype)
|
||||
e = e->ctfeInterpret();
|
||||
sc = sc->endCTFE();
|
||||
|
||||
// pragma(msg) is allowed to contain types as well as expressions
|
||||
e = ctfeInterpretForPragmaMsg(e);
|
||||
if (e->op == TOKerror)
|
||||
{ errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
|
||||
return;
|
||||
@@ -1040,8 +1044,11 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
Expression *e = (*args)[0];
|
||||
|
||||
e = e->ctfeSemantic(sc);
|
||||
sc = sc->startCTFE();
|
||||
e = e->semantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc->endCTFE();
|
||||
|
||||
e = e->ctfeInterpret();
|
||||
(*args)[0] = e;
|
||||
if (e->op == TOKerror)
|
||||
@@ -1049,12 +1056,25 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
StringExp *se = e->toString();
|
||||
if (!se)
|
||||
error("string expected for library name, not '%s'", e->toChars());
|
||||
else if (global.params.verbose)
|
||||
else
|
||||
{
|
||||
char *name = (char *)mem.malloc(se->len + 1);
|
||||
memcpy(name, se->string, se->len);
|
||||
name[se->len] = 0;
|
||||
printf("library %s\n", name);
|
||||
if (global.params.verbose)
|
||||
fprintf(global.stdmsg, "library %s\n", name);
|
||||
if (global.params.moduleDeps && !global.params.moduleDepsFile)
|
||||
{
|
||||
OutBuffer *ob = global.params.moduleDeps;
|
||||
Module* imod = sc->instantiatingModule ? sc->instantiatingModule : sc->module;
|
||||
ob->writestring("depsLib ");
|
||||
ob->writestring(imod->toPrettyChars());
|
||||
ob->writestring(" (");
|
||||
escapePath(ob, imod->srcfile->toChars());
|
||||
ob->writestring(") : ");
|
||||
ob->writestring((char *) name);
|
||||
ob->writenl();
|
||||
}
|
||||
mem.free(name);
|
||||
}
|
||||
}
|
||||
@@ -1068,8 +1088,12 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
else
|
||||
{
|
||||
Expression *e = (*args)[0];
|
||||
e = e->ctfeSemantic(sc);
|
||||
|
||||
sc = sc->startCTFE();
|
||||
e = e->semantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc->endCTFE();
|
||||
|
||||
e = e->ctfeInterpret();
|
||||
(*args)[0] = e;
|
||||
Dsymbol *sa = getDsymbol(e);
|
||||
@@ -1107,6 +1131,47 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
|
||||
if (se->sz != 1)
|
||||
error("mangled name characters can only be of type char");
|
||||
|
||||
#if 1
|
||||
/* Note: D language specification should not have any assumption about backend
|
||||
* implementation. Ideally pragma(mangle) can accept a string of any content.
|
||||
*
|
||||
* Therefore, this validation is compiler implementation specific.
|
||||
*/
|
||||
for (size_t i = 0; i < se->len; )
|
||||
{
|
||||
utf8_t *p = (utf8_t *)se->string;
|
||||
dchar_t c = p[i];
|
||||
if (c < 0x80)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z' ||
|
||||
c >= 'a' && c <= 'z' ||
|
||||
c >= '0' && c <= '9' ||
|
||||
c != 0 && strchr("$%().:?@[]_", c))
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
error("char 0x%02x not allowed in mangled name", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (const char* msg = utf_decodeChar((utf8_t *)se->string, se->len, &i, &c))
|
||||
{
|
||||
error("%s", msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isUniAlpha(c))
|
||||
{
|
||||
error("char 0x%04x not allowed in mangled name", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if IN_LLVM
|
||||
@@ -1121,27 +1186,28 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
/* Print unrecognized pragmas
|
||||
*/
|
||||
printf("pragma %s", ident->toChars());
|
||||
fprintf(global.stdmsg, "pragma %s", ident->toChars());
|
||||
if (args)
|
||||
{
|
||||
for (size_t i = 0; i < args->dim; i++)
|
||||
{
|
||||
Expression *e = (*args)[i];
|
||||
|
||||
#if IN_LLVM
|
||||
// ignore errors in ignored pragmas.
|
||||
global.gag++;
|
||||
unsigned errors_save = global.errors;
|
||||
#endif
|
||||
e = e->ctfeSemantic(sc);
|
||||
sc = sc->startCTFE();
|
||||
e = e->semantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc->endCTFE();
|
||||
|
||||
e = e->ctfeInterpret();
|
||||
if (i == 0)
|
||||
printf(" (");
|
||||
fprintf(global.stdmsg, " (");
|
||||
else
|
||||
printf(",");
|
||||
printf("%s", e->toChars());
|
||||
|
||||
fprintf(global.stdmsg, ",");
|
||||
fprintf(global.stdmsg, "%s", e->toChars());
|
||||
#if IN_LLVM
|
||||
// restore error state.
|
||||
global.gag--;
|
||||
@@ -1149,9 +1215,9 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
#endif
|
||||
}
|
||||
if (args->dim)
|
||||
printf(")");
|
||||
fprintf(global.stdmsg, ")");
|
||||
}
|
||||
printf("\n");
|
||||
fprintf(global.stdmsg, "\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1198,10 +1264,10 @@ Lnodecl:
|
||||
}
|
||||
}
|
||||
|
||||
int PragmaDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
bool PragmaDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
*ps = NULL;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *PragmaDeclaration::kind()
|
||||
@@ -1244,7 +1310,7 @@ Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
|
||||
}
|
||||
|
||||
|
||||
int ConditionalDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
bool ConditionalDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
//printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
|
||||
if (condition->inc)
|
||||
@@ -1252,8 +1318,13 @@ int ConditionalDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
Dsymbols *d = condition->include(NULL, NULL) ? decl : elsedecl;
|
||||
return Dsymbol::oneMembers(d, ps, ident);
|
||||
}
|
||||
*ps = NULL;
|
||||
return TRUE;
|
||||
else
|
||||
{
|
||||
bool res = (Dsymbol::oneMembers( decl, ps, ident) && *ps == NULL &&
|
||||
Dsymbol::oneMembers(elsedecl, ps, ident) && *ps == NULL);
|
||||
*ps = NULL;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionalDeclaration::emitComment(Scope *sc)
|
||||
@@ -1317,7 +1388,7 @@ void ConditionalDeclaration::importAll(Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionalDeclaration::addComment(unsigned char *comment)
|
||||
void ConditionalDeclaration::addComment(utf8_t *comment)
|
||||
{
|
||||
/* Because addComment is called by the parser, if we called
|
||||
* include() it would define a version before it was used.
|
||||
@@ -1529,6 +1600,9 @@ Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
|
||||
int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
//printf("CompileDeclaration::addMember(sc = %p, sd = %p, memnum = %d)\n", sc, sd, memnum);
|
||||
if (compiled)
|
||||
return 1;
|
||||
|
||||
this->sd = sd;
|
||||
if (memnum == 0)
|
||||
{ /* No members yet, so parse the mixin now
|
||||
@@ -1543,8 +1617,10 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
void CompileDeclaration::compileIt(Scope *sc)
|
||||
{
|
||||
//printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
|
||||
exp = exp->ctfeSemantic(sc);
|
||||
sc = sc->startCTFE();
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
sc = sc->endCTFE();
|
||||
exp = exp->ctfeInterpret();
|
||||
StringExp *se = exp->toString();
|
||||
if (!se)
|
||||
@@ -1553,12 +1629,15 @@ void CompileDeclaration::compileIt(Scope *sc)
|
||||
else
|
||||
{
|
||||
se = se->toUTF8(sc);
|
||||
Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
|
||||
p.loc = loc;
|
||||
Parser p(sc->module, (utf8_t *)se->string, se->len, 0);
|
||||
p.scanloc = loc;
|
||||
p.nextToken();
|
||||
unsigned errors = global.errors;
|
||||
decl = p.parseDeclDefs(0);
|
||||
if (p.token.value != TOKeof)
|
||||
exp->error("incomplete mixin declaration (%s)", se->toChars());
|
||||
if (global.errors != errors)
|
||||
decl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+45
-33
@@ -17,18 +17,19 @@
|
||||
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Expression;
|
||||
struct Statement;
|
||||
struct LabelDsymbol;
|
||||
struct Initializer;
|
||||
struct Module;
|
||||
struct Condition;
|
||||
class Expression;
|
||||
class Statement;
|
||||
class LabelDsymbol;
|
||||
class Initializer;
|
||||
class Module;
|
||||
class Condition;
|
||||
struct HdrGenState;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct AttribDeclaration : Dsymbol
|
||||
class AttribDeclaration : public Dsymbol
|
||||
{
|
||||
public:
|
||||
Dsymbols *decl; // array of Dsymbol's
|
||||
|
||||
AttribDeclaration(Dsymbols *decl);
|
||||
@@ -36,21 +37,21 @@ struct AttribDeclaration : Dsymbol
|
||||
int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
void setScopeNewSc(Scope *sc,
|
||||
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
|
||||
StorageClass newstc, LINK linkage, PROT protection, int explictProtection,
|
||||
structalign_t structalign);
|
||||
void semanticNewSc(Scope *sc,
|
||||
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
|
||||
StorageClass newstc, LINK linkage, PROT protection, int explictProtection,
|
||||
structalign_t structalign);
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
void addComment(unsigned char *comment);
|
||||
void addComment(utf8_t *comment);
|
||||
void emitComment(Scope *sc);
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
int hasPointers();
|
||||
bool hasPointers();
|
||||
bool hasStaticCtorOrDtor();
|
||||
void checkCtorConstInit();
|
||||
void addLocalClass(ClassDeclarations *);
|
||||
@@ -67,23 +68,25 @@ struct AttribDeclaration : Dsymbol
|
||||
#endif
|
||||
};
|
||||
|
||||
struct StorageClassDeclaration : AttribDeclaration
|
||||
class StorageClassDeclaration : public AttribDeclaration
|
||||
{
|
||||
public:
|
||||
StorageClass stc;
|
||||
|
||||
StorageClassDeclaration(StorageClass stc, Dsymbols *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void setScope(Scope *sc);
|
||||
void semantic(Scope *sc);
|
||||
int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
static const char *stcToChars(char tmp[], StorageClass& stc);
|
||||
static void stcToCBuffer(OutBuffer *buf, StorageClass stc);
|
||||
};
|
||||
|
||||
struct DeprecatedDeclaration : StorageClassDeclaration
|
||||
class DeprecatedDeclaration : public StorageClassDeclaration
|
||||
{
|
||||
public:
|
||||
Expression *msg;
|
||||
|
||||
DeprecatedDeclaration(Expression *msg, Dsymbols *decl);
|
||||
@@ -92,11 +95,12 @@ struct DeprecatedDeclaration : StorageClassDeclaration
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct LinkDeclaration : AttribDeclaration
|
||||
class LinkDeclaration : public AttribDeclaration
|
||||
{
|
||||
enum LINK linkage;
|
||||
public:
|
||||
LINK linkage;
|
||||
|
||||
LinkDeclaration(enum LINK p, Dsymbols *decl);
|
||||
LinkDeclaration(LINK p, Dsymbols *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void setScope(Scope *sc);
|
||||
void semantic(Scope *sc);
|
||||
@@ -105,22 +109,24 @@ struct LinkDeclaration : AttribDeclaration
|
||||
char *toChars();
|
||||
};
|
||||
|
||||
struct ProtDeclaration : AttribDeclaration
|
||||
class ProtDeclaration : public AttribDeclaration
|
||||
{
|
||||
enum PROT protection;
|
||||
public:
|
||||
PROT protection;
|
||||
|
||||
ProtDeclaration(enum PROT p, Dsymbols *decl);
|
||||
ProtDeclaration(PROT p, Dsymbols *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void importAll(Scope *sc);
|
||||
void setScope(Scope *sc);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
static void protectionToCBuffer(OutBuffer *buf, enum PROT protection);
|
||||
static void protectionToCBuffer(OutBuffer *buf, PROT protection);
|
||||
};
|
||||
|
||||
struct AlignDeclaration : AttribDeclaration
|
||||
class AlignDeclaration : public AttribDeclaration
|
||||
{
|
||||
public:
|
||||
unsigned salign;
|
||||
|
||||
AlignDeclaration(unsigned sa, Dsymbols *decl);
|
||||
@@ -130,13 +136,14 @@ struct AlignDeclaration : AttribDeclaration
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct AnonDeclaration : AttribDeclaration
|
||||
class AnonDeclaration : public AttribDeclaration
|
||||
{
|
||||
public:
|
||||
bool isunion;
|
||||
structalign_t alignment;
|
||||
int sem; // 1 if successful semantic()
|
||||
|
||||
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);
|
||||
AnonDeclaration(Loc loc, bool isunion, Dsymbols *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
@@ -144,15 +151,16 @@ struct AnonDeclaration : AttribDeclaration
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
struct PragmaDeclaration : AttribDeclaration
|
||||
class PragmaDeclaration : public AttribDeclaration
|
||||
{
|
||||
public:
|
||||
Expressions *args; // array of Expression's
|
||||
|
||||
PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
void semantic(Scope *sc);
|
||||
void setScope(Scope *sc);
|
||||
int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
|
||||
@@ -165,25 +173,27 @@ struct PragmaDeclaration : AttribDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ConditionalDeclaration : AttribDeclaration
|
||||
class ConditionalDeclaration : public AttribDeclaration
|
||||
{
|
||||
public:
|
||||
Condition *condition;
|
||||
Dsymbols *elsedecl; // array of Dsymbol's for else block
|
||||
|
||||
ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
void emitComment(Scope *sc);
|
||||
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
|
||||
void addComment(unsigned char *comment);
|
||||
void addComment(utf8_t *comment);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void toJson(JsonOut *json);
|
||||
void importAll(Scope *sc);
|
||||
void setScope(Scope *sc);
|
||||
};
|
||||
|
||||
struct StaticIfDeclaration : ConditionalDeclaration
|
||||
class StaticIfDeclaration : public ConditionalDeclaration
|
||||
{
|
||||
public:
|
||||
ScopeDsymbol *sd;
|
||||
int addisdone;
|
||||
|
||||
@@ -199,8 +209,9 @@ struct StaticIfDeclaration : ConditionalDeclaration
|
||||
|
||||
// Mixin declarations
|
||||
|
||||
struct CompileDeclaration : AttribDeclaration
|
||||
class CompileDeclaration : public AttribDeclaration
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
|
||||
ScopeDsymbol *sd;
|
||||
@@ -219,8 +230,9 @@ struct CompileDeclaration : AttribDeclaration
|
||||
* User defined attributes look like:
|
||||
* [ args, ... ]
|
||||
*/
|
||||
struct UserAttributeDeclaration : AttribDeclaration
|
||||
class UserAttributeDeclaration : public AttribDeclaration
|
||||
{
|
||||
public:
|
||||
Expressions *atts;
|
||||
|
||||
UserAttributeDeclaration(Expressions *atts, Dsymbols *decl);
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@
|
||||
* Determine if function is a builtin one that we can
|
||||
* evaluate at compile time.
|
||||
*/
|
||||
enum BUILTIN FuncDeclaration::isBuiltin()
|
||||
BUILTIN FuncDeclaration::isBuiltin()
|
||||
{
|
||||
static const char FeZe [] = "FNaNbNfeZe"; // @safe pure nothrow real function(real)
|
||||
static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real)
|
||||
@@ -154,7 +154,7 @@ uinteger_t eval_bswap(Expression *arg0)
|
||||
* Return result; NULL if cannot evaluate it.
|
||||
*/
|
||||
|
||||
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments)
|
||||
Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments)
|
||||
{
|
||||
assert(arguments && arguments->dim);
|
||||
Expression *arg0 = (*arguments)[0];
|
||||
|
||||
+35
-6
@@ -56,14 +56,15 @@ int lambdaCanThrow(Expression *e, void *param)
|
||||
switch (e->op)
|
||||
{
|
||||
case TOKdeclaration:
|
||||
{ DeclarationExp *de = (DeclarationExp *)e;
|
||||
{
|
||||
DeclarationExp *de = (DeclarationExp *)e;
|
||||
pct->can = Dsymbol_canThrow(de->declaration, pct->mustnot);
|
||||
break;
|
||||
}
|
||||
|
||||
case TOKcall:
|
||||
{ CallExp *ce = (CallExp *)e;
|
||||
|
||||
{
|
||||
CallExp *ce = (CallExp *)e;
|
||||
if (global.errors && !ce->e1->type)
|
||||
break; // error recovery
|
||||
|
||||
@@ -79,14 +80,15 @@ int lambdaCanThrow(Expression *e, void *param)
|
||||
else
|
||||
{
|
||||
if (pct->mustnot)
|
||||
e->error("%s is not nothrow", ce->e1->toChars());
|
||||
e->error("'%s' is not nothrow", ce->f ? ce->f->toPrettyChars() : ce->e1->toChars());
|
||||
pct->can = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TOKnew:
|
||||
{ NewExp *ne = (NewExp *)e;
|
||||
{
|
||||
NewExp *ne = (NewExp *)e;
|
||||
if (ne->member)
|
||||
{
|
||||
// See if constructor call can throw
|
||||
@@ -102,6 +104,33 @@ int lambdaCanThrow(Expression *e, void *param)
|
||||
break;
|
||||
}
|
||||
|
||||
case TOKassign:
|
||||
case TOKconstruct:
|
||||
{
|
||||
/* Element-wise assignment could invoke postblits.
|
||||
*/
|
||||
AssignExp *ae = (AssignExp *)e;
|
||||
if (ae->e1->op != TOKslice)
|
||||
break;
|
||||
|
||||
Type *tv = ae->e1->type->toBasetype()->nextOf()->baseElemOf();
|
||||
if (tv->ty != Tstruct)
|
||||
break;
|
||||
StructDeclaration *sd = ((TypeStruct *)tv)->sym;
|
||||
if (!sd->postblit || sd->postblit->type->ty != Tfunction)
|
||||
break;
|
||||
|
||||
if (((TypeFunction *)sd->postblit->type)->isnothrow)
|
||||
;
|
||||
else
|
||||
{
|
||||
if (pct->mustnot)
|
||||
e->error("'%s' is not nothrow", sd->postblit->toPrettyChars());
|
||||
pct->can = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TOKnewanonclass:
|
||||
assert(0); // should have been lowered by semantic()
|
||||
break;
|
||||
@@ -175,7 +204,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
|
||||
else if ((td = s->isTupleDeclaration()) != NULL)
|
||||
{
|
||||
for (size_t i = 0; i < td->objects->dim; i++)
|
||||
{ Object *o = (*td->objects)[i];
|
||||
{ RootObject *o = (*td->objects)[i];
|
||||
if (o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{ Expression *eo = (Expression *)o;
|
||||
if (eo->op == TOKdsymbol)
|
||||
|
||||
+80
-46
@@ -163,7 +163,7 @@ MATCH Expression::implicitConvTo(Type *t)
|
||||
type = Type::terror;
|
||||
}
|
||||
Expression *e = optimize(WANTvalue | WANTflags);
|
||||
if (e->type == t)
|
||||
if (e->type->equals(t))
|
||||
return MATCHexact;
|
||||
if (e != this)
|
||||
{ //printf("\toptimized to %s of type %s\n", e->toChars(), e->type->toChars());
|
||||
@@ -351,8 +351,8 @@ MATCH IntegerExp::implicitConvTo(Type *t)
|
||||
}
|
||||
else
|
||||
{
|
||||
f = (float)(long long)value;
|
||||
if (f != (long long)value)
|
||||
f = (float)(sinteger_t)value;
|
||||
if (f != (sinteger_t)value)
|
||||
goto Lno;
|
||||
}
|
||||
goto Lyes;
|
||||
@@ -369,8 +369,8 @@ MATCH IntegerExp::implicitConvTo(Type *t)
|
||||
}
|
||||
else
|
||||
{
|
||||
f = (double)(long long)value;
|
||||
if (f != (long long)value)
|
||||
f = (double)(sinteger_t)value;
|
||||
if (f != (sinteger_t)value)
|
||||
goto Lno;
|
||||
}
|
||||
goto Lyes;
|
||||
@@ -387,8 +387,8 @@ MATCH IntegerExp::implicitConvTo(Type *t)
|
||||
}
|
||||
else
|
||||
{
|
||||
f = ldouble((long long)value);
|
||||
if (f != (long long)value)
|
||||
f = ldouble((sinteger_t)value);
|
||||
if (f != (sinteger_t)value)
|
||||
goto Lno;
|
||||
}
|
||||
goto Lyes;
|
||||
@@ -418,6 +418,11 @@ Lno:
|
||||
return MATCHnomatch;
|
||||
}
|
||||
|
||||
MATCH ErrorExp::implicitConvTo(Type *t)
|
||||
{
|
||||
return MATCHnomatch;
|
||||
}
|
||||
|
||||
MATCH NullExp::implicitConvTo(Type *t)
|
||||
{
|
||||
#if 0
|
||||
@@ -431,7 +436,7 @@ MATCH NullExp::implicitConvTo(Type *t)
|
||||
* and mutable to immutable. It works because, after all, a null
|
||||
* doesn't actually point to anything.
|
||||
*/
|
||||
if (t->invariantOf()->equals(type->invariantOf()))
|
||||
if (t->immutableOf()->equals(type->immutableOf()))
|
||||
return MATCHconst;
|
||||
|
||||
return Expression::implicitConvTo(t);
|
||||
@@ -655,7 +660,7 @@ MATCH CallExp::implicitConvTo(Type *t)
|
||||
* convert to immutable
|
||||
*/
|
||||
if (f && f->isolateReturn())
|
||||
return type->invariantOf()->implicitConvTo(t);
|
||||
return type->immutableOf()->implicitConvTo(t);
|
||||
|
||||
/* The result of arr.dup and arr.idup can be unique essentially.
|
||||
* So deal with this case specially.
|
||||
@@ -680,7 +685,7 @@ MATCH CallExp::implicitConvTo(Type *t)
|
||||
return MATCHnomatch;
|
||||
}
|
||||
}
|
||||
m = type->invariantOf()->implicitConvTo(t);
|
||||
m = type->immutableOf()->implicitConvTo(t);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -1021,8 +1026,7 @@ Type *SliceExp::toStaticArrayType()
|
||||
if (lwr->isConst() && upr->isConst())
|
||||
{
|
||||
size_t len = upr->toUInteger() - lwr->toUInteger();
|
||||
return new TypeSArray(type->toBasetype()->nextOf(),
|
||||
new IntegerExp(Loc(), len, Type::tindex));
|
||||
return TypeSArray::makeType(loc, type->toBasetype()->nextOf(), len);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -1049,6 +1053,7 @@ MATCH SliceExp::implicitConvTo(Type *t)
|
||||
|
||||
/**************************************
|
||||
* Do an explicit cast.
|
||||
* Assume that the 'this' expression does not have any indirections.
|
||||
*/
|
||||
|
||||
Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
@@ -1058,21 +1063,21 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
printf("Expression::castTo(this=%s, type=%s, t=%s)\n",
|
||||
toChars(), type->toChars(), t->toChars());
|
||||
#endif
|
||||
if (type == t)
|
||||
if (type->equals(t))
|
||||
return this;
|
||||
if (op == TOKvar)
|
||||
{
|
||||
VarDeclaration *v = ((VarExp *)this)->var->isVarDeclaration();
|
||||
if (v && v->storage_class & STCmanifest)
|
||||
{
|
||||
Expression *e = optimize(WANTvalue | WANTinterpret);
|
||||
Expression *e = ctfeInterpret();
|
||||
return e->castTo(sc, t);
|
||||
}
|
||||
}
|
||||
Expression *e = this;
|
||||
Type *tb = t->toBasetype();
|
||||
Type *typeb = type->toBasetype();
|
||||
if (tb != typeb)
|
||||
if (!tb->equals(typeb))
|
||||
{
|
||||
// Do (type *) cast of (type [dim])
|
||||
if (tb->ty == Tpointer &&
|
||||
@@ -1140,7 +1145,7 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
else if (typeb->implicitConvTo(tb) == MATCHconst && t == type->constOf())
|
||||
else if (typeb->implicitConvTo(tb) == MATCHconst && t->equals(type->constOf()))
|
||||
{
|
||||
Expression *e = copy();
|
||||
e->type = t;
|
||||
@@ -1167,8 +1172,9 @@ Expression *ErrorExp::castTo(Scope *sc, Type *t)
|
||||
|
||||
|
||||
Expression *RealExp::castTo(Scope *sc, Type *t)
|
||||
{ Expression *e = this;
|
||||
if (type != t)
|
||||
{
|
||||
Expression *e = this;
|
||||
if (!type->equals(t))
|
||||
{
|
||||
if ((type->isreal() && t->isreal()) ||
|
||||
(type->isimaginary() && t->isimaginary())
|
||||
@@ -1184,8 +1190,9 @@ Expression *RealExp::castTo(Scope *sc, Type *t)
|
||||
|
||||
|
||||
Expression *ComplexExp::castTo(Scope *sc, Type *t)
|
||||
{ Expression *e = this;
|
||||
if (type != t)
|
||||
{
|
||||
Expression *e = this;
|
||||
if (!type->equals(t))
|
||||
{
|
||||
if (type->iscomplex() && t->iscomplex())
|
||||
{ e = copy();
|
||||
@@ -1200,8 +1207,8 @@ Expression *ComplexExp::castTo(Scope *sc, Type *t)
|
||||
|
||||
Expression *NullExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
//printf("NullExp::castTo(t = %p)\n", t);
|
||||
if (type == t)
|
||||
//printf("NullExp::castTo(t = %s) %s\n", t->toChars(), toChars());
|
||||
if (type->equals(t))
|
||||
{
|
||||
committed = 1;
|
||||
return this;
|
||||
@@ -1212,7 +1219,7 @@ Expression *NullExp::castTo(Scope *sc, Type *t)
|
||||
Type *tb = t->toBasetype();
|
||||
#if 0
|
||||
e->type = type->toBasetype();
|
||||
if (tb != e->type)
|
||||
if (!tb->equals(e->type))
|
||||
{
|
||||
// NULL implicitly converts to any pointer type or dynamic array
|
||||
if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
|
||||
@@ -1243,6 +1250,10 @@ Expression *NullExp::castTo(Scope *sc, Type *t)
|
||||
return e->Expression::castTo(sc, t);
|
||||
}
|
||||
#endif
|
||||
if (tb->ty == Tsarray || tb->ty == Tstruct)
|
||||
{
|
||||
error("cannot cast null to %s", t->toChars());
|
||||
}
|
||||
e->type = t;
|
||||
return e;
|
||||
}
|
||||
@@ -1278,7 +1289,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
||||
copied = 1;
|
||||
}
|
||||
|
||||
if (type == t)
|
||||
if (type->equals(t))
|
||||
{
|
||||
return se;
|
||||
}
|
||||
@@ -1289,7 +1300,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
||||
return Expression::castTo(sc, t);
|
||||
|
||||
Type *typeb = type->toBasetype();
|
||||
if (typeb == tb)
|
||||
if (typeb->equals(tb))
|
||||
{
|
||||
if (!copied)
|
||||
{ se = (StringExp *)copy();
|
||||
@@ -1308,6 +1319,16 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
||||
se->len = (len * sz) / se->sz;
|
||||
se->committed = 1;
|
||||
se->type = t;
|
||||
|
||||
/* Assure space for terminating 0
|
||||
*/
|
||||
if ((se->len + 1) * se->sz > (len + 1) * sz)
|
||||
{
|
||||
void *s = (void *)mem.malloc((se->len + 1) * se->sz);
|
||||
memcpy(s, se->string, se->len * se->sz);
|
||||
memset((char *)s + se->len * se->sz, 0, se->sz);
|
||||
se->string = s;
|
||||
}
|
||||
return se;
|
||||
}
|
||||
|
||||
@@ -1357,7 +1378,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
||||
case X(Tchar, Twchar):
|
||||
for (size_t u = 0; u < len;)
|
||||
{ unsigned c;
|
||||
const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
|
||||
const char *p = utf_decodeChar((utf8_t *)se->string, len, &u, &c);
|
||||
if (p)
|
||||
error("%s", p);
|
||||
else
|
||||
@@ -1370,7 +1391,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
||||
case X(Tchar, Tdchar):
|
||||
for (size_t u = 0; u < len;)
|
||||
{ unsigned c;
|
||||
const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
|
||||
const char *p = utf_decodeChar((utf8_t *)se->string, len, &u, &c);
|
||||
if (p)
|
||||
error("%s", p);
|
||||
buffer.write4(c);
|
||||
@@ -1469,7 +1490,7 @@ L2:
|
||||
// Copy when changing the string literal
|
||||
size_t newsz = se->sz;
|
||||
size_t d = (dim2 < se->len) ? dim2 : se->len;
|
||||
void *s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
|
||||
void *s = (void *)mem.malloc((dim2 + 1) * newsz);
|
||||
memcpy(s, se->string, d * newsz);
|
||||
// Extend with 0, add terminating 0
|
||||
memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
|
||||
@@ -1498,7 +1519,7 @@ Expression *AddrExp::castTo(Scope *sc, Type *t)
|
||||
|
||||
tb = t->toBasetype();
|
||||
type = type->toBasetype();
|
||||
if (tb != type)
|
||||
if (!tb->equals(type))
|
||||
{
|
||||
// Look for pointers to functions where the functions are overloaded.
|
||||
|
||||
@@ -1559,6 +1580,9 @@ Expression *AddrExp::castTo(Scope *sc, Type *t)
|
||||
|
||||
Expression *TupleExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
if (type->equals(t))
|
||||
return this;
|
||||
|
||||
TupleExp *e = (TupleExp *)copy();
|
||||
e->e0 = e0 ? e0->copy() : NULL;
|
||||
e->exps = (Expressions *)exps->copy();
|
||||
@@ -1674,12 +1698,12 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
|
||||
printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
|
||||
toChars(), type->toChars(), t->toChars());
|
||||
#endif
|
||||
if (type == t && hasOverloads == 0)
|
||||
if (type == t && !hasOverloads)
|
||||
return this;
|
||||
Expression *e;
|
||||
Type *tb = t->toBasetype();
|
||||
Type *typeb = type->toBasetype();
|
||||
if (tb != typeb)
|
||||
if (!tb->equals(typeb))
|
||||
{
|
||||
// Look for pointers to functions where the functions are overloaded.
|
||||
FuncDeclaration *f;
|
||||
@@ -1732,7 +1756,7 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
|
||||
else
|
||||
{ e = copy();
|
||||
e->type = t;
|
||||
((SymOffExp *)e)->hasOverloads = 0;
|
||||
((SymOffExp *)e)->hasOverloads = false;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
@@ -1743,12 +1767,12 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t)
|
||||
printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
|
||||
toChars(), type->toChars(), t->toChars());
|
||||
#endif
|
||||
static char msg[] = "cannot form delegate due to covariant return type";
|
||||
static const char msg[] = "cannot form delegate due to covariant return type";
|
||||
|
||||
Expression *e = this;
|
||||
Type *tb = t->toBasetype();
|
||||
Type *typeb = type->toBasetype();
|
||||
if (tb != typeb || hasOverloads)
|
||||
if (!tb->equals(typeb) || hasOverloads)
|
||||
{
|
||||
// Look for delegates to functions where the functions are overloaded.
|
||||
FuncDeclaration *f;
|
||||
@@ -1810,7 +1834,7 @@ Expression *CondExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
Expression *e = this;
|
||||
|
||||
if (type != t)
|
||||
if (!type->equals(t))
|
||||
{
|
||||
if (1 || e1->op == TOKstring || e2->op == TOKstring)
|
||||
{ e = new CondExp(loc, econd, e1->castTo(sc, t), e2->castTo(sc, t));
|
||||
@@ -1852,6 +1876,14 @@ Expression *SliceExp::castTo(Scope *sc, Type *t)
|
||||
e = copy();
|
||||
e->type = t;
|
||||
}
|
||||
else if (typeb->ty == Tarray && tb->ty == Tarray &&
|
||||
typeb->nextOf()->constConv(tb->nextOf()) == MATCHconst)
|
||||
{
|
||||
// immutable(T)[] to const(T)[]
|
||||
// T [] to const(T)[]
|
||||
e = copy();
|
||||
e->type = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = Expression::castTo(sc, t);
|
||||
@@ -2200,13 +2232,13 @@ Lagain:
|
||||
|
||||
if (t1b->ty == ty1) // if no promotions
|
||||
{
|
||||
if (t1 == t2)
|
||||
if (t1->equals(t2))
|
||||
{
|
||||
t = t1;
|
||||
goto Lret;
|
||||
}
|
||||
|
||||
if (t1b == t2b)
|
||||
if (t1b->equals(t2b))
|
||||
{
|
||||
t = t1b;
|
||||
goto Lret;
|
||||
@@ -2228,8 +2260,14 @@ Lagain:
|
||||
t1 = t1b;
|
||||
t2 = t2b;
|
||||
|
||||
if (t1 == t2)
|
||||
if (t1->ty == Ttuple || t2->ty == Ttuple)
|
||||
goto Lincompatible;
|
||||
|
||||
if (t1->equals(t2))
|
||||
{
|
||||
// merging can not result in new enum type
|
||||
if (t->ty == Tenum)
|
||||
t = t1b;
|
||||
}
|
||||
else if ((t1->ty == Tpointer && t2->ty == Tpointer) ||
|
||||
(t1->ty == Tdelegate && t2->ty == Tdelegate))
|
||||
@@ -2238,12 +2276,8 @@ Lagain:
|
||||
Type *t1n = t1->nextOf();
|
||||
Type *t2n = t2->nextOf();
|
||||
|
||||
if (t1n == t2n)
|
||||
if (t1n->equals(t2n))
|
||||
;
|
||||
#if IN_LLVM
|
||||
else if (t1n->equals(t2n))
|
||||
;
|
||||
#endif
|
||||
else if (t1n->ty == Tvoid) // pointers to void are always compatible
|
||||
t = t2;
|
||||
else if (t2n->ty == Tvoid)
|
||||
@@ -2800,8 +2834,8 @@ Expression *Expression::integralPromotions(Scope *sc)
|
||||
|
||||
int arrayTypeCompatible(Loc loc, Type *t1, Type *t2)
|
||||
{
|
||||
t1 = t1->toBasetype();
|
||||
t2 = t2->toBasetype();
|
||||
t1 = t1->toBasetype()->merge2();
|
||||
t2 = t2->toBasetype()->merge2();
|
||||
|
||||
if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
|
||||
(t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
|
||||
@@ -2864,7 +2898,7 @@ IntRange Expression::getIntRange()
|
||||
|
||||
IntRange IntegerExp::getIntRange()
|
||||
{
|
||||
return IntRange(value).cast(type) DUMP;
|
||||
return IntRange(SignExtendedNumber(value)).cast(type) DUMP;
|
||||
}
|
||||
|
||||
IntRange CastExp::getIntRange()
|
||||
|
||||
+242
-233
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -32,16 +32,15 @@
|
||||
|
||||
/********************************* ClassDeclaration ****************************/
|
||||
|
||||
ClassDeclaration *ClassDeclaration::classinfo;
|
||||
ClassDeclaration *ClassDeclaration::object;
|
||||
ClassDeclaration *ClassDeclaration::throwable;
|
||||
ClassDeclaration *ClassDeclaration::exception;
|
||||
ClassDeclaration *ClassDeclaration::errorException;
|
||||
|
||||
ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
|
||||
ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, bool inObject)
|
||||
: AggregateDeclaration(loc, id)
|
||||
{
|
||||
static char msg[] = "only object.d can define this reserved class name";
|
||||
static const char msg[] = "only object.d can define this reserved class name";
|
||||
|
||||
if (baseclasses)
|
||||
// Actually, this is a transfer
|
||||
@@ -79,147 +78,140 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
|
||||
if (id->toChars()[0] == 'T')
|
||||
{
|
||||
if (id == Id::TypeInfo)
|
||||
{ if (Type::typeinfo)
|
||||
Type::typeinfo->error("%s", msg);
|
||||
Type::typeinfo = this;
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::dtypeinfo = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Class)
|
||||
{ if (Type::typeinfoclass)
|
||||
Type::typeinfoclass->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfoclass = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Interface)
|
||||
{ if (Type::typeinfointerface)
|
||||
Type::typeinfointerface->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfointerface = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Struct)
|
||||
{ if (Type::typeinfostruct)
|
||||
Type::typeinfostruct->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfostruct = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Typedef)
|
||||
{ if (Type::typeinfotypedef)
|
||||
Type::typeinfotypedef->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfotypedef = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Pointer)
|
||||
{ if (Type::typeinfopointer)
|
||||
Type::typeinfopointer->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfopointer = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Array)
|
||||
{ if (Type::typeinfoarray)
|
||||
Type::typeinfoarray->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfoarray = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_StaticArray)
|
||||
{ //if (Type::typeinfostaticarray)
|
||||
{ //if (!inObject)
|
||||
//Type::typeinfostaticarray->error("%s", msg);
|
||||
Type::typeinfostaticarray = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_AssociativeArray)
|
||||
{ if (Type::typeinfoassociativearray)
|
||||
Type::typeinfoassociativearray->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfoassociativearray = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Enum)
|
||||
{ if (Type::typeinfoenum)
|
||||
Type::typeinfoenum->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfoenum = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Function)
|
||||
{ if (Type::typeinfofunction)
|
||||
Type::typeinfofunction->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfofunction = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Delegate)
|
||||
{ if (Type::typeinfodelegate)
|
||||
Type::typeinfodelegate->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfodelegate = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Tuple)
|
||||
{ if (Type::typeinfotypelist)
|
||||
Type::typeinfotypelist->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfotypelist = this;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
if (id == Id::TypeInfo_Const)
|
||||
{ if (Type::typeinfoconst)
|
||||
Type::typeinfoconst->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfoconst = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Invariant)
|
||||
{ if (Type::typeinfoinvariant)
|
||||
Type::typeinfoinvariant->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfoinvariant = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Shared)
|
||||
{ if (Type::typeinfoshared)
|
||||
Type::typeinfoshared->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfoshared = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Wild)
|
||||
{ if (Type::typeinfowild)
|
||||
Type::typeinfowild->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfowild = this;
|
||||
}
|
||||
|
||||
if (id == Id::TypeInfo_Vector)
|
||||
{ if (Type::typeinfovector)
|
||||
Type::typeinfovector->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
Type::typeinfovector = this;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (id == Id::Object)
|
||||
{ if (object)
|
||||
object->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
object = this;
|
||||
}
|
||||
|
||||
if (id == Id::Throwable)
|
||||
{ if (throwable)
|
||||
throwable->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
throwable = this;
|
||||
}
|
||||
|
||||
if (id == Id::Exception)
|
||||
{ if (exception)
|
||||
exception->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
exception = this;
|
||||
}
|
||||
|
||||
if (id == Id::Error)
|
||||
{ if (errorException)
|
||||
errorException->error("%s", msg);
|
||||
{ if (!inObject)
|
||||
error("%s", msg);
|
||||
errorException = this;
|
||||
}
|
||||
|
||||
//if (id == Id::ClassInfo)
|
||||
if (id == Id::TypeInfo_Class)
|
||||
{ if (classinfo)
|
||||
classinfo->error("%s", msg);
|
||||
classinfo = this;
|
||||
}
|
||||
|
||||
#if !MODULEINFO_IS_STRUCT
|
||||
#ifdef DMDV2
|
||||
if (id == Id::ModuleInfo && !Module::moduleinfo)
|
||||
@@ -227,7 +219,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
|
||||
#else
|
||||
if (id == Id::ModuleInfo)
|
||||
{ if (Module::moduleinfo)
|
||||
Module::moduleinfo->error("%s", msg);
|
||||
error("%s", msg);
|
||||
Module::moduleinfo = this;
|
||||
}
|
||||
#endif
|
||||
@@ -235,6 +227,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
|
||||
}
|
||||
|
||||
com = 0;
|
||||
cpp = 0;
|
||||
isscope = 0;
|
||||
isabstract = 0;
|
||||
inuse = 0;
|
||||
@@ -302,7 +295,8 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
{
|
||||
sc = scope;
|
||||
scx = scope; // save so we don't make redundant copies
|
||||
scope = NULL;
|
||||
}
|
||||
@@ -316,17 +310,21 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
userAttributes = sc->userAttributes;
|
||||
|
||||
if (sc->linkage == LINKcpp)
|
||||
error("cannot create C++ classes");
|
||||
cpp = 1;
|
||||
|
||||
// Expand any tuples in baseclasses[]
|
||||
for (size_t i = 0; i < baseclasses->dim; )
|
||||
{ BaseClass *b = (*baseclasses)[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
Type *tb = b->type->toBasetype();
|
||||
{
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = ungagSpeculative();
|
||||
|
||||
BaseClass *b = (*baseclasses)[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
|
||||
Type *tb = b->type->toBasetype();
|
||||
if (tb->ty == Ttuple)
|
||||
{ TypeTuple *tup = (TypeTuple *)tb;
|
||||
enum PROT protection = b->protection;
|
||||
PROT protection = b->protection;
|
||||
baseclasses->remove(i);
|
||||
size_t dim = Parameter::dim(tup->arguments);
|
||||
for (size_t j = 0; j < dim; j++)
|
||||
@@ -341,21 +339,23 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
|
||||
// See if there's a base class as first in baseclasses[]
|
||||
if (baseclasses->dim)
|
||||
{ TypeClass *tc;
|
||||
BaseClass *b;
|
||||
Type *tb;
|
||||
{
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = ungagSpeculative();
|
||||
|
||||
b = (*baseclasses)[0];
|
||||
BaseClass *b = (*baseclasses)[0];
|
||||
//b->type = b->type->semantic(loc, sc);
|
||||
tb = b->type->toBasetype();
|
||||
|
||||
Type *tb = b->type->toBasetype();
|
||||
if (tb->ty != Tclass)
|
||||
{ if (b->type != Type::terror)
|
||||
{
|
||||
if (b->type != Type::terror)
|
||||
error("base type must be class or interface, not %s", b->type->toChars());
|
||||
baseclasses->remove(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tc = (TypeClass *)(tb);
|
||||
TypeClass *tc = (TypeClass *)(tb);
|
||||
|
||||
if (tc->sym->isDeprecated())
|
||||
{
|
||||
@@ -411,19 +411,18 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
// Treat the remaining entries in baseclasses as interfaces
|
||||
// Check for errors, handle forward references
|
||||
for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; )
|
||||
{ TypeClass *tc;
|
||||
BaseClass *b;
|
||||
Type *tb;
|
||||
{
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = ungagSpeculative();
|
||||
|
||||
b = (*baseclasses)[i];
|
||||
BaseClass *b = (*baseclasses)[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
tb = b->type->toBasetype();
|
||||
if (tb->ty == Tclass)
|
||||
tc = (TypeClass *)tb;
|
||||
else
|
||||
tc = NULL;
|
||||
|
||||
Type *tb = b->type->toBasetype();
|
||||
TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
|
||||
if (!tc || !tc->sym->isInterfaceDeclaration())
|
||||
{ if (b->type != Type::terror)
|
||||
{
|
||||
if (b->type != Type::terror)
|
||||
error("base type must be interface, not %s", b->type->toChars());
|
||||
baseclasses->remove(i);
|
||||
continue;
|
||||
@@ -475,63 +474,65 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
doAncestorsSemantic = SemanticDone;
|
||||
|
||||
|
||||
// If no base class, and this is not an Object, use Object as base class
|
||||
if (!baseClass && ident != Id::Object)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
error("missing or corrupt object.d");
|
||||
fatal();
|
||||
}
|
||||
|
||||
Type *t = object->type;
|
||||
t = t->semantic(loc, sc)->toBasetype();
|
||||
assert(t->ty == Tclass);
|
||||
TypeClass *tc = (TypeClass *)t;
|
||||
|
||||
BaseClass *b = new BaseClass(tc, PROTpublic);
|
||||
baseclasses->shift(b);
|
||||
|
||||
baseClass = tc->sym;
|
||||
assert(!baseClass->isInterfaceDeclaration());
|
||||
b->base = baseClass;
|
||||
}
|
||||
|
||||
interfaces_dim = baseclasses->dim;
|
||||
interfaces = baseclasses->tdata();
|
||||
|
||||
|
||||
if (baseClass)
|
||||
{
|
||||
if (baseClass->storage_class & STCfinal)
|
||||
error("cannot inherit from final class %s", baseClass->toChars());
|
||||
|
||||
interfaces_dim--;
|
||||
interfaces++;
|
||||
|
||||
// Copy vtbl[] from base class
|
||||
vtbl.setDim(baseClass->vtbl.dim);
|
||||
memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
|
||||
|
||||
// Inherit properties from base class
|
||||
com = baseClass->isCOMclass();
|
||||
isscope = baseClass->isscope;
|
||||
vthis = baseClass->vthis;
|
||||
enclosing = baseClass->enclosing;
|
||||
storage_class |= baseClass->storage_class & STC_TYPECTOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No base class, so this is the root of the class hierarchy
|
||||
vtbl.setDim(0);
|
||||
vtbl.push(this); // leave room for classinfo as first member
|
||||
}
|
||||
|
||||
protection = sc->protection;
|
||||
storage_class |= sc->stc;
|
||||
|
||||
if (sizeok == SIZEOKnone)
|
||||
{
|
||||
// If no base class, and this is not an Object, use Object as base class
|
||||
if (!baseClass && ident != Id::Object && !cpp)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
error("missing or corrupt object.d");
|
||||
fatal();
|
||||
}
|
||||
|
||||
Type *t = object->type;
|
||||
t = t->semantic(loc, sc)->toBasetype();
|
||||
assert(t->ty == Tclass);
|
||||
TypeClass *tc = (TypeClass *)t;
|
||||
|
||||
BaseClass *b = new BaseClass(tc, PROTpublic);
|
||||
baseclasses->shift(b);
|
||||
|
||||
baseClass = tc->sym;
|
||||
assert(!baseClass->isInterfaceDeclaration());
|
||||
b->base = baseClass;
|
||||
}
|
||||
|
||||
interfaces_dim = baseclasses->dim;
|
||||
interfaces = baseclasses->tdata();
|
||||
|
||||
if (baseClass)
|
||||
{
|
||||
if (baseClass->storage_class & STCfinal)
|
||||
error("cannot inherit from final class %s", baseClass->toChars());
|
||||
|
||||
interfaces_dim--;
|
||||
interfaces++;
|
||||
|
||||
// Copy vtbl[] from base class
|
||||
vtbl.setDim(baseClass->vtbl.dim);
|
||||
memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
|
||||
|
||||
// Inherit properties from base class
|
||||
com = baseClass->isCOMclass();
|
||||
if (baseClass->isCPPclass())
|
||||
cpp = 1;
|
||||
isscope = baseClass->isscope;
|
||||
vthis = baseClass->vthis;
|
||||
enclosing = baseClass->enclosing;
|
||||
storage_class |= baseClass->storage_class & STC_TYPECTOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No base class, so this is the root of the class hierarchy
|
||||
vtbl.setDim(0);
|
||||
if (vtblOffset())
|
||||
vtbl.push(this); // leave room for classinfo as first member
|
||||
}
|
||||
|
||||
protection = sc->protection;
|
||||
storage_class |= sc->stc;
|
||||
|
||||
interfaceSemantic(sc);
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
@@ -544,7 +545,8 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
* member which is a pointer to the enclosing scope.
|
||||
*/
|
||||
if (vthis) // if inheriting from nested class
|
||||
{ // Use the base class's 'this' member
|
||||
{
|
||||
// Use the base class's 'this' member
|
||||
if (storage_class & STCstatic)
|
||||
error("static class cannot inherit from nested class %s", baseClass->toChars());
|
||||
if (toParent2() != baseClass->toParent2() &&
|
||||
@@ -570,14 +572,14 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
makeNested();
|
||||
}
|
||||
|
||||
if (storage_class & STCauto)
|
||||
error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
|
||||
if (storage_class & STCscope)
|
||||
isscope = 1;
|
||||
if (storage_class & STCabstract)
|
||||
isabstract = 1;
|
||||
if (storage_class & STCauto)
|
||||
error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
|
||||
if (storage_class & STCscope)
|
||||
isscope = 1;
|
||||
if (storage_class & STCabstract)
|
||||
isabstract = 1;
|
||||
}
|
||||
|
||||
sc = sc->push(this);
|
||||
//sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
|
||||
@@ -585,7 +587,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
sc->stc &= STCsafe | STCtrusted | STCsystem;
|
||||
sc->parent = this;
|
||||
sc->inunion = 0;
|
||||
|
||||
if (isCOMclass())
|
||||
{
|
||||
if (global.params.isWindows)
|
||||
@@ -600,13 +601,19 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
sc->explicitProtection = 0;
|
||||
sc->structalign = STRUCTALIGN_DEFAULT;
|
||||
if (baseClass)
|
||||
{ sc->offset = baseClass->structsize;
|
||||
{
|
||||
sc->offset = baseClass->structsize;
|
||||
alignsize = baseClass->alignsize;
|
||||
sc->offset = (sc->offset + alignsize - 1) & ~(alignsize - 1);
|
||||
// if (enclosing)
|
||||
// sc->offset += Target::ptrsize; // room for uplevel context pointer
|
||||
}
|
||||
else
|
||||
{ sc->offset = Target::ptrsize * 2; // allow room for __vptr and __monitor
|
||||
{
|
||||
if (cpp)
|
||||
sc->offset = Target::ptrsize; // allow room for __vptr
|
||||
else
|
||||
sc->offset = Target::ptrsize * 2; // allow room for __vptr and __monitor
|
||||
alignsize = Target::ptrsize;
|
||||
}
|
||||
sc->userAttributes = NULL;
|
||||
@@ -619,50 +626,45 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
* resolve individual members like enums.
|
||||
*/
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
/* There are problems doing this in the general case because
|
||||
* Scope keeps track of things like 'offset'
|
||||
*/
|
||||
if (s->isEnumDeclaration() ||
|
||||
(s->isAggregateDeclaration() && s->ident) ||
|
||||
s->isTemplateMixin() ||
|
||||
s->isAttribDeclaration() ||
|
||||
s->isAliasDeclaration())
|
||||
{
|
||||
//printf("[%d] setScope %s %s, sc = %p\n", i, s->kind(), s->toChars(), sc);
|
||||
s->setScope(sc);
|
||||
}
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
//printf("[%d] setScope %s %s, sc = %p\n", i, s->kind(), s->toChars(), sc);
|
||||
s->setScope(sc);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < members_dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = ungagSpeculative();
|
||||
s->semantic(sc);
|
||||
}
|
||||
|
||||
// Set the offsets of the fields and determine the size of the class
|
||||
|
||||
unsigned offset = structsize;
|
||||
bool isunion = isUnionDeclaration() != NULL;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->setFieldOffset(this, &offset, false);
|
||||
}
|
||||
sc->offset = structsize;
|
||||
|
||||
if (global.errors != errors)
|
||||
{ // The type is no good.
|
||||
{
|
||||
// The type is no good.
|
||||
type = Type::terror;
|
||||
}
|
||||
|
||||
if (sizeok == SIZEOKfwd) // failed due to forward references
|
||||
{ // semantic() failed due to forward references
|
||||
{
|
||||
// semantic() failed due to forward references
|
||||
// Unwind what we did, and defer it for later
|
||||
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{ Dsymbol *s = fields[i];
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (vd)
|
||||
vd->offset = 0;
|
||||
{
|
||||
if (VarDeclaration *v = fields[i])
|
||||
v->offset = 0;
|
||||
}
|
||||
fields.setDim(0);
|
||||
structsize = 0;
|
||||
@@ -688,11 +690,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
/* Look for special member functions.
|
||||
* They must be in this class, not in a base class.
|
||||
*/
|
||||
ctor = search(Loc(), Id::ctor, 0);
|
||||
#if DMDV1
|
||||
if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
|
||||
ctor = NULL;
|
||||
#else
|
||||
searchCtor();
|
||||
if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration())))
|
||||
ctor = NULL; // search() looks through ancestor classes
|
||||
if (!ctor && noDefaultCtor)
|
||||
@@ -705,11 +703,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
::error(v->loc, "field %s must be initialized in constructor", v->toChars());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// dtor = (DtorDeclaration *)search(Id::dtor, 0);
|
||||
// if (dtor && dtor->toParent() != this)
|
||||
// dtor = NULL;
|
||||
|
||||
inv = buildInv(sc);
|
||||
|
||||
@@ -722,10 +715,14 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
// this() { }
|
||||
if (!ctor && baseClass && baseClass->ctor)
|
||||
{
|
||||
if (resolveFuncCall(loc, sc, baseClass->ctor, NULL, NULL, NULL, 1))
|
||||
if (FuncDeclaration *fd = resolveFuncCall(loc, sc, baseClass->ctor, NULL, NULL, NULL, 1))
|
||||
{
|
||||
//printf("Creating default this(){} for class %s\n", toChars());
|
||||
Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0);
|
||||
TypeFunction *btf = (TypeFunction *)fd->type;
|
||||
TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class);
|
||||
tf->purity = btf->purity;
|
||||
tf->isnothrow = btf->isnothrow;
|
||||
tf->trust = btf->trust;
|
||||
CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf);
|
||||
ctor->fbody = new CompoundStatement(Loc(), new Statements());
|
||||
members->push(ctor);
|
||||
@@ -787,7 +784,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
if (FuncDeclaration *f = hasIdentityOpAssign(sc))
|
||||
{
|
||||
if (!(f->storage_class & STCdisable))
|
||||
error("identity assignment operator overload is illegal");
|
||||
error(f->loc, "identity assignment operator overload is illegal");
|
||||
}
|
||||
sc->pop();
|
||||
|
||||
@@ -808,14 +805,12 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
deferred->semantic3(sc);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
|
||||
{
|
||||
printf("this = %p %s\n", this, this->toChars());
|
||||
printf("type = %d sym = %p\n", type->ty, ((TypeClass *)type)->sym);
|
||||
error("failed semantic analysis");
|
||||
this->errors = true;
|
||||
type = Type::terror;
|
||||
}
|
||||
#endif
|
||||
assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
|
||||
}
|
||||
|
||||
void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
@@ -899,10 +894,10 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
|
||||
{
|
||||
/* cd->baseClass might not be set if cd is forward referenced.
|
||||
*/
|
||||
if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
|
||||
if (!cd->baseClass && cd->scope && !cd->isInterfaceDeclaration())
|
||||
{
|
||||
cd->semantic(NULL);
|
||||
if (!cd->baseClass)
|
||||
if (!cd->baseClass && cd->scope)
|
||||
cd->error("base class is forward referenced by %s", toChars());
|
||||
}
|
||||
|
||||
@@ -941,14 +936,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
// must semantic on base class/interfaces
|
||||
doAncestorsSemantic = SemanticIn;
|
||||
|
||||
// If speculatively gagged, ungag now.
|
||||
unsigned oldgag = global.gag;
|
||||
if (global.isSpeculativeGagging())
|
||||
global.gag = 0;
|
||||
semantic(scope);
|
||||
global.gag = oldgag;
|
||||
|
||||
if (doAncestorsSemantic != SemanticDone)
|
||||
doAncestorsSemantic = SemanticStart;
|
||||
}
|
||||
@@ -995,6 +983,8 @@ ClassDeclaration *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
|
||||
{
|
||||
BaseClass *b = (*baseclasses)[i];
|
||||
ClassDeclaration *cdb = b->type->isClassHandle();
|
||||
if (!cdb) // Bugzilla 10616
|
||||
return NULL;
|
||||
if (cdb->ident->equals(ident))
|
||||
return cdb;
|
||||
cdb = cdb->searchBase(loc, ident);
|
||||
@@ -1010,10 +1000,13 @@ ClassDeclaration *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
|
||||
*/
|
||||
|
||||
#if DMDV2
|
||||
int isf(void *param, FuncDeclaration *fd)
|
||||
int isf(void *param, Dsymbol *s)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (!fd)
|
||||
return 0;
|
||||
//printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
|
||||
return param == fd;
|
||||
return (RootObject *)param == fd;
|
||||
}
|
||||
|
||||
int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
|
||||
@@ -1021,7 +1014,8 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
|
||||
//printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
|
||||
Dsymbol *s = search(Loc(), fd->ident, 4|2);
|
||||
if (!s)
|
||||
{ //printf("not found\n");
|
||||
{
|
||||
//printf("not found\n");
|
||||
/* Because, due to a hack, if there are multiple definitions
|
||||
* of fd->ident, NULL is returned.
|
||||
*/
|
||||
@@ -1032,9 +1026,10 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
|
||||
if (os)
|
||||
{
|
||||
for (size_t i = 0; i < os->a.dim; i++)
|
||||
{ Dsymbol *s2 = os->a[i];
|
||||
{
|
||||
Dsymbol *s2 = os->a[i];
|
||||
FuncDeclaration *f2 = s2->isFuncDeclaration();
|
||||
if (f2 && overloadApply(f2, &isf, fd))
|
||||
if (f2 && overloadApply(f2, (void *)fd, &isf))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -1043,7 +1038,7 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
|
||||
{
|
||||
FuncDeclaration *fdstart = s->isFuncDeclaration();
|
||||
//printf("%s fdstart = %p\n", s->kind(), fdstart);
|
||||
if (overloadApply(fdstart, &isf, fd))
|
||||
if (overloadApply(fdstart, (void *)fd, &isf))
|
||||
return 0;
|
||||
|
||||
return !fd->parent->isTemplateMixin();
|
||||
@@ -1152,9 +1147,13 @@ void ClassDeclaration::interfaceSemantic(Scope *sc)
|
||||
if (b->base->isCOMinterface())
|
||||
com = 1;
|
||||
|
||||
#if 1
|
||||
if (b->base->isCPPinterface() && id)
|
||||
id->cpp = 1;
|
||||
|
||||
#else
|
||||
if (b->base->isCPPinterface())
|
||||
cpp = 1;
|
||||
#endif
|
||||
vtblInterfaces->push(b);
|
||||
b->copyBaseInterfaces(vtblInterfaces);
|
||||
}
|
||||
@@ -1174,6 +1173,11 @@ int ClassDeclaration::isCOMinterface()
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int ClassDeclaration::isCPPclass()
|
||||
{
|
||||
return cpp;
|
||||
}
|
||||
|
||||
int ClassDeclaration::isCPPinterface()
|
||||
{
|
||||
return 0;
|
||||
@@ -1184,10 +1188,10 @@ int ClassDeclaration::isCPPinterface()
|
||||
/****************************************
|
||||
*/
|
||||
|
||||
int ClassDeclaration::isAbstract()
|
||||
bool ClassDeclaration::isAbstract()
|
||||
{
|
||||
if (isabstract)
|
||||
return TRUE;
|
||||
return true;
|
||||
for (size_t i = 1; i < vtbl.dim; i++)
|
||||
{
|
||||
FuncDeclaration *fd = vtbl[i]->isFuncDeclaration();
|
||||
@@ -1196,10 +1200,10 @@ int ClassDeclaration::isAbstract()
|
||||
if (!fd || fd->isAbstract())
|
||||
{
|
||||
isabstract |= 1;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1208,11 +1212,14 @@ int ClassDeclaration::isAbstract()
|
||||
* For class objects, yes, this is where the classinfo ptr goes.
|
||||
* For COM interfaces, no.
|
||||
* For non-COM interfaces, yes, this is where the Interface ptr goes.
|
||||
* Returns:
|
||||
* 0 vtbl[0] is first virtual function pointer
|
||||
* 1 vtbl[0] is classinfo/interfaceinfo pointer
|
||||
*/
|
||||
|
||||
int ClassDeclaration::vtblOffset()
|
||||
{
|
||||
return 1;
|
||||
return cpp ? 0 : 1;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
@@ -1236,8 +1243,6 @@ void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
|
||||
InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
|
||||
: ClassDeclaration(loc, id, baseclasses)
|
||||
{
|
||||
com = 0;
|
||||
cpp = 0;
|
||||
if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces
|
||||
{ com = 1;
|
||||
cpp = 1; // IUnknown is also a C++ interface
|
||||
@@ -1284,7 +1289,8 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
{
|
||||
sc = scope;
|
||||
scx = scope; // save so we don't make redundant copies
|
||||
scope = NULL;
|
||||
}
|
||||
@@ -1299,13 +1305,17 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
|
||||
// Expand any tuples in baseclasses[]
|
||||
for (size_t i = 0; i < baseclasses->dim; )
|
||||
{ BaseClass *b = (*baseclasses)[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
Type *tb = b->type->toBasetype();
|
||||
{
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = ungagSpeculative();
|
||||
|
||||
BaseClass *b = (*baseclasses)[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
|
||||
Type *tb = b->type->toBasetype();
|
||||
if (tb->ty == Ttuple)
|
||||
{ TypeTuple *tup = (TypeTuple *)tb;
|
||||
enum PROT protection = b->protection;
|
||||
PROT protection = b->protection;
|
||||
baseclasses->remove(i);
|
||||
size_t dim = Parameter::dim(tup->arguments);
|
||||
for (size_t j = 0; j < dim; j++)
|
||||
@@ -1323,19 +1333,18 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
|
||||
// Check for errors, handle forward references
|
||||
for (size_t i = 0; i < baseclasses->dim; )
|
||||
{ TypeClass *tc;
|
||||
BaseClass *b;
|
||||
Type *tb;
|
||||
{
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = ungagSpeculative();
|
||||
|
||||
b = (*baseclasses)[i];
|
||||
BaseClass *b = (*baseclasses)[i];
|
||||
b->type = b->type->semantic(loc, sc);
|
||||
tb = b->type->toBasetype();
|
||||
if (tb->ty == Tclass)
|
||||
tc = (TypeClass *)tb;
|
||||
else
|
||||
tc = NULL;
|
||||
|
||||
Type *tb = b->type->toBasetype();
|
||||
TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
|
||||
if (!tc || !tc->sym->isInterfaceDeclaration())
|
||||
{ if (b->type != Type::terror)
|
||||
{
|
||||
if (b->type != Type::terror)
|
||||
error("base type must be interface, not %s", b->type->toChars());
|
||||
baseclasses->remove(i);
|
||||
continue;
|
||||
@@ -1432,9 +1441,9 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
sc = sc->push(this);
|
||||
sc->stc &= STCsafe | STCtrusted | STCsystem;
|
||||
sc->parent = this;
|
||||
if (isCOMinterface())
|
||||
if (com)
|
||||
sc->linkage = LINKwindows;
|
||||
else if (isCPPinterface())
|
||||
else if (cpp)
|
||||
sc->linkage = LINKcpp;
|
||||
sc->structalign = STRUCTALIGN_DEFAULT;
|
||||
sc->protection = PROTpublic;
|
||||
@@ -1463,6 +1472,9 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = ungagSpeculative();
|
||||
s->semantic(sc);
|
||||
}
|
||||
|
||||
@@ -1476,14 +1488,12 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
||||
sc->pop();
|
||||
//printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
|
||||
|
||||
#if 0
|
||||
if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
|
||||
{
|
||||
printf("this = %p %s\n", this, this->toChars());
|
||||
printf("type = %d sym = %p\n", type->ty, ((TypeClass *)type)->sym);
|
||||
error("failed semantic analysis");
|
||||
this->errors = true;
|
||||
type = Type::terror;
|
||||
}
|
||||
#endif
|
||||
assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1618,7 +1628,7 @@ BaseClass::BaseClass()
|
||||
memset(this, 0, sizeof(BaseClass));
|
||||
}
|
||||
|
||||
BaseClass::BaseClass(Type *type, enum PROT protection)
|
||||
BaseClass::BaseClass(Type *type, PROT protection)
|
||||
{
|
||||
//printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
|
||||
this->type = type;
|
||||
@@ -1643,7 +1653,6 @@ BaseClass::BaseClass(Type *type, enum PROT protection)
|
||||
|
||||
int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance)
|
||||
{
|
||||
ClassDeclaration *id = base;
|
||||
int result = 0;
|
||||
|
||||
//printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
|
||||
|
||||
+231
-62
@@ -135,13 +135,10 @@ int StructDeclaration::needOpAssign()
|
||||
assert(v && v->isField());
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
Type *tv = v->type->baseElemOf();
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->needOpAssign())
|
||||
goto Lneed;
|
||||
@@ -164,7 +161,7 @@ Lneed:
|
||||
* Note that s will be constructed onto the stack, and probably
|
||||
* copy-constructed in caller site.
|
||||
*
|
||||
* If S has copy copy construction and/or destructor,
|
||||
* If S has copy copy construction and/or destructor,
|
||||
* the body will make bit-wise object swap:
|
||||
* S __tmp = this; // bit copy
|
||||
* this = s; // bit copy
|
||||
@@ -192,19 +189,46 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
||||
return NULL;
|
||||
|
||||
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
|
||||
StorageClass stc = STCundefined;
|
||||
StorageClass stc = STCsafe | STCnothrow | STCpure;
|
||||
Loc declLoc = this->loc;
|
||||
Loc loc = Loc(); // internal code should have no loc to prevent coverage
|
||||
|
||||
if (dtor || postblit)
|
||||
{
|
||||
if (dtor)
|
||||
stc = mergeFuncAttrs(stc, dtor->storage_class);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < fields.dim; i++)
|
||||
{
|
||||
Dsymbol *s = fields[i];
|
||||
VarDeclaration *v = s->isVarDeclaration();
|
||||
assert(v && v->isField());
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->baseElemOf();
|
||||
if (tv->ty == Tstruct)
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (FuncDeclaration *f = sd->hasIdentityOpAssign(sc))
|
||||
stc = mergeFuncAttrs(stc, f->storage_class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Parameters *fparams = new Parameters;
|
||||
fparams->push(new Parameter(STCnodtor, type, Id::p, NULL));
|
||||
Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
|
||||
((TypeFunction *)ftype)->isref = 1;
|
||||
Type *tf = new TypeFunction(fparams, handle, 0, LINKd, stc | STCref);
|
||||
|
||||
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, ftype);
|
||||
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, tf);
|
||||
|
||||
Expression *e = NULL;
|
||||
if (dtor || postblit)
|
||||
if (stc & STCdisable)
|
||||
{
|
||||
}
|
||||
else if (dtor || postblit)
|
||||
{
|
||||
/* Do swap this and rhs
|
||||
* tmp = this; this = s; tmp.dtor();
|
||||
@@ -258,15 +282,18 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
|
||||
e = Expression::combine(e, ec);
|
||||
}
|
||||
}
|
||||
Statement *s1 = new ExpStatement(loc, e);
|
||||
if (e)
|
||||
{
|
||||
Statement *s1 = new ExpStatement(loc, e);
|
||||
|
||||
/* Add:
|
||||
* return this;
|
||||
*/
|
||||
e = new ThisExp(loc);
|
||||
Statement *s2 = new ReturnStatement(loc, e);
|
||||
/* Add:
|
||||
* return this;
|
||||
*/
|
||||
e = new ThisExp(loc);
|
||||
Statement *s2 = new ReturnStatement(loc, e);
|
||||
|
||||
fop->fbody = new CompoundStatement(loc, s1, s2);
|
||||
fop->fbody = new CompoundStatement(loc, s1, s2);
|
||||
}
|
||||
|
||||
Dsymbol *s = fop;
|
||||
#if 1 // workaround until fixing issue 1528
|
||||
@@ -347,12 +374,10 @@ int StructDeclaration::needOpEquals()
|
||||
goto Lneed;
|
||||
if (tv->ty == Tclass)
|
||||
goto Lneed;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
tv = tv->baseElemOf();
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->needOpEquals())
|
||||
goto Lneed;
|
||||
@@ -384,7 +409,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
|
||||
Type *tthis;
|
||||
if (i == 0) tthis = type;
|
||||
if (i == 1) tthis = type->constOf();
|
||||
if (i == 2) tthis = type->invariantOf();
|
||||
if (i == 2) tthis = type->immutableOf();
|
||||
if (i == 3) tthis = type->sharedOf();
|
||||
if (i == 4) tthis = type->sharedConstOf();
|
||||
if (i == 5) break;
|
||||
@@ -449,9 +474,48 @@ FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
|
||||
FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
|
||||
{
|
||||
if (!needOpEquals())
|
||||
return NULL;
|
||||
return NULL; // bitwise comparison would work
|
||||
|
||||
//printf("StructDeclaration::buildXopEquals() %s\n", toChars());
|
||||
if (Dsymbol *eq = search_function(this, Id::eq))
|
||||
{
|
||||
if (FuncDeclaration *fd = eq->isFuncDeclaration())
|
||||
{
|
||||
TypeFunction *tfeqptr;
|
||||
{
|
||||
Scope sc;
|
||||
|
||||
/* const bool opEquals(ref const S s);
|
||||
*/
|
||||
Parameters *parameters = new Parameters;
|
||||
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
|
||||
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
|
||||
tfeqptr->mod = MODconst;
|
||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &sc);
|
||||
}
|
||||
fd = fd->overloadExactMatch(tfeqptr);
|
||||
if (fd)
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xerreq)
|
||||
{
|
||||
Identifier *id = Lexer::idPool("_xopEquals");
|
||||
Expression *e = new IdentifierExp(loc, Id::empty);
|
||||
e = new DotIdExp(loc, e, Id::object);
|
||||
e = new DotIdExp(loc, e, id);
|
||||
e = e->semantic(sc);
|
||||
Dsymbol *s = getDsymbol(e);
|
||||
if (!s)
|
||||
{
|
||||
::error(Loc(), "ICE: %s not found in object module. You must update druntime", id->toChars());
|
||||
fatal();
|
||||
}
|
||||
assert(s);
|
||||
xerreq = s->isFuncDeclaration();
|
||||
}
|
||||
|
||||
Loc declLoc = Loc(); // loc is unnecessary so __xopEquals is never called directly
|
||||
Loc loc = Loc(); // loc is unnecessary so errors are gagged
|
||||
|
||||
@@ -470,42 +534,143 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
|
||||
|
||||
fop->fbody = new ReturnStatement(loc, e);
|
||||
|
||||
size_t index = members->dim;
|
||||
members->push(fop);
|
||||
|
||||
unsigned errors = global.startGagging(); // Do not report errors, even if the
|
||||
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
|
||||
global.speculativeGag = global.gag;
|
||||
unsigned errors = global.startGagging(); // Do not report errors
|
||||
Scope *sc2 = sc->push();
|
||||
sc2->stc = 0;
|
||||
sc2->linkage = LINKd;
|
||||
sc2->speculative = true;
|
||||
|
||||
fop->semantic(sc2);
|
||||
fop->semantic2(sc2);
|
||||
fop->semantic3(sc2);
|
||||
|
||||
sc2->pop();
|
||||
global.speculativeGag = oldspec;
|
||||
if (global.endGagging(errors)) // if errors happened
|
||||
{
|
||||
members->remove(index);
|
||||
|
||||
if (!xerreq)
|
||||
{
|
||||
Expression *e = new IdentifierExp(loc, Id::empty);
|
||||
e = new DotIdExp(loc, e, Id::object);
|
||||
e = new DotIdExp(loc, e, Lexer::idPool("_xopEquals"));
|
||||
e = e->semantic(sc);
|
||||
Dsymbol *s = getDsymbol(e);
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
|
||||
xerreq = fd;
|
||||
}
|
||||
fop = xerreq;
|
||||
|
||||
return fop;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Build __xopCmp for TypeInfo_Struct
|
||||
* static bool __xopCmp(ref const S p, ref const S q)
|
||||
* {
|
||||
* return p.opCmp(q);
|
||||
* }
|
||||
*
|
||||
* This is called by TypeInfo.compare(p1, p2). If the struct does not support
|
||||
* const objects comparison, it will throw "not implemented" Error in runtime.
|
||||
*/
|
||||
|
||||
FuncDeclaration *StructDeclaration::buildXopCmp(Scope *sc)
|
||||
{
|
||||
//printf("StructDeclaration::buildXopCmp() %s\n", toChars());
|
||||
if (Dsymbol *cmp = search_function(this, Id::cmp))
|
||||
{
|
||||
if (FuncDeclaration *fd = cmp->isFuncDeclaration())
|
||||
{
|
||||
TypeFunction *tfcmpptr;
|
||||
{
|
||||
Scope sc;
|
||||
|
||||
/* const int opCmp(ref const S s);
|
||||
*/
|
||||
Parameters *parameters = new Parameters;
|
||||
parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL));
|
||||
tfcmpptr = new TypeFunction(parameters, Type::tint32, 0, LINKd);
|
||||
tfcmpptr->mod = MODconst;
|
||||
tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &sc);
|
||||
}
|
||||
fd = fd->overloadExactMatch(tfcmpptr);
|
||||
if (fd)
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
else
|
||||
fop->addMember(sc, this, 1);
|
||||
{
|
||||
#if 0 // FIXME: doesn't work for recursive alias this
|
||||
/* Check opCmp member exists.
|
||||
* Consider 'alias this', but except opDispatch.
|
||||
*/
|
||||
Expression *e = new DsymbolExp(loc, this);
|
||||
e = new DotIdExp(loc, e, Id::cmp);
|
||||
Scope *sc2 = sc->push();
|
||||
e = e->trySemantic(sc2);
|
||||
sc2->pop();
|
||||
if (e)
|
||||
{
|
||||
Dsymbol *s = NULL;
|
||||
switch (e->op)
|
||||
{
|
||||
case TOKoverloadset: s = ((OverExp *)e)->vars; break;
|
||||
case TOKimport: s = ((ScopeExp *)e)->sds; break;
|
||||
case TOKvar: s = ((VarExp *)e)->var; break;
|
||||
default: break;
|
||||
}
|
||||
if (!s || s->ident != Id::cmp)
|
||||
e = NULL; // there's no valid member 'opCmp'
|
||||
}
|
||||
if (!e)
|
||||
return NULL; // bitwise comparison would work
|
||||
/* Essentially, a struct which does not define opCmp is not comparable.
|
||||
* At this time, typeid(S).compare might be correct that throwing "not implement" Error.
|
||||
* But implementing it would break existing code, such as:
|
||||
*
|
||||
* struct S { int value; } // no opCmp
|
||||
* int[S] aa; // Currently AA key uses bitwise comparison
|
||||
* // (It's default behavior of TypeInfo_Strust.compare).
|
||||
*
|
||||
* Not sure we should fix this inconsistency, so just keep current behavior.
|
||||
*/
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!xerrcmp)
|
||||
{
|
||||
Identifier *id = Lexer::idPool("_xopCmp");
|
||||
Expression *e = new IdentifierExp(loc, Id::empty);
|
||||
e = new DotIdExp(loc, e, Id::object);
|
||||
e = new DotIdExp(loc, e, id);
|
||||
e = e->semantic(sc);
|
||||
Dsymbol *s = getDsymbol(e);
|
||||
if (!s)
|
||||
{
|
||||
::error(Loc(), "ICE: %s not found in object module. You must update druntime", id->toChars());
|
||||
fatal();
|
||||
}
|
||||
assert(s);
|
||||
xerrcmp = s->isFuncDeclaration();
|
||||
}
|
||||
|
||||
Loc declLoc = Loc(); // loc is unnecessary so __xopCmp is never called directly
|
||||
Loc loc = Loc(); // loc is unnecessary so errors are gagged
|
||||
|
||||
Parameters *parameters = new Parameters;
|
||||
parameters->push(new Parameter(STCref | STCconst, type, Id::p, NULL));
|
||||
parameters->push(new Parameter(STCref | STCconst, type, Id::q, NULL));
|
||||
TypeFunction *tf = new TypeFunction(parameters, Type::tint32, 0, LINKd);
|
||||
tf = (TypeFunction *)tf->semantic(loc, sc);
|
||||
|
||||
Identifier *id = Lexer::idPool("__xopCmp");
|
||||
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), id, STCstatic, tf);
|
||||
|
||||
Expression *e1 = new IdentifierExp(loc, Id::p);
|
||||
Expression *e2 = new IdentifierExp(loc, Id::q);
|
||||
Expression *e = new CallExp(loc, new DotIdExp(loc, e1, Id::cmp), e2);
|
||||
|
||||
fop->fbody = new ReturnStatement(loc, e);
|
||||
|
||||
unsigned errors = global.startGagging(); // Do not report errors
|
||||
Scope *sc2 = sc->push();
|
||||
sc2->stc = 0;
|
||||
sc2->linkage = LINKd;
|
||||
|
||||
fop->semantic(sc2);
|
||||
fop->semantic2(sc2);
|
||||
|
||||
sc2->pop();
|
||||
if (global.endGagging(errors)) // if errors happened
|
||||
fop = xerrcmp;
|
||||
|
||||
return fop;
|
||||
}
|
||||
@@ -542,14 +707,14 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
|
||||
|
||||
stc = mergeFuncAttrs(stc, postblit->storage_class);
|
||||
if (stc & STCsafe) // change to @trusted for unsafe casts
|
||||
stc = stc & ~STCsafe | STCtrusted;
|
||||
stc = (stc & ~STCsafe) | STCtrusted;
|
||||
|
||||
Parameters *fparams = new Parameters;
|
||||
fparams->push(new Parameter(STCref, type->constOf(), Id::p, NULL));
|
||||
Type *ftype = new TypeFunction(fparams, Type::tvoid, 0, LINKd, stc);
|
||||
ftype->mod = MODconst;
|
||||
Type *tf = new TypeFunction(fparams, Type::tvoid, 0, LINKd, stc);
|
||||
tf->mod = MODconst;
|
||||
|
||||
FuncDeclaration *fcp = new FuncDeclaration(declLoc, Loc(), Id::cpctor, stc, ftype);
|
||||
FuncDeclaration *fcp = new FuncDeclaration(declLoc, Loc(), Id::cpctor, stc, tf);
|
||||
|
||||
if (!(stc & STCdisable))
|
||||
{
|
||||
@@ -612,12 +777,14 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
|
||||
Type *tv = v->type->toBasetype();
|
||||
dinteger_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
{
|
||||
TypeSArray *tsa = (TypeSArray *)tv;
|
||||
dim *= tsa->dim->toInteger();
|
||||
tv = tsa->next->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->postblit && dim)
|
||||
{
|
||||
@@ -726,12 +893,14 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
|
||||
Type *tv = v->type->toBasetype();
|
||||
dinteger_t dim = 1;
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
dim *= ((TypeSArray *)tv)->dim->toInteger();
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
{
|
||||
TypeSArray *tsa = (TypeSArray *)tv;
|
||||
dim *= tsa->dim->toInteger();
|
||||
tv = tsa->next->toBasetype();
|
||||
}
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor && dim)
|
||||
{
|
||||
|
||||
+54
-18
@@ -84,16 +84,41 @@ DebugCondition::DebugCondition(Module *mod, unsigned level, Identifier *ident)
|
||||
{
|
||||
}
|
||||
|
||||
// Helper for printing dependency information
|
||||
void printDepsConditional(Scope *sc, DVCondition* condition, const char* depType)
|
||||
{
|
||||
if (!global.params.moduleDeps || global.params.moduleDepsFile)
|
||||
return;
|
||||
OutBuffer *ob = global.params.moduleDeps;
|
||||
Module* imod = sc ? (sc->instantiatingModule ? sc->instantiatingModule : sc->module) : condition->mod;
|
||||
if (!imod)
|
||||
return;
|
||||
ob->writestring(depType);
|
||||
ob->writestring(imod->toPrettyChars());
|
||||
ob->writestring(" (");
|
||||
escapePath(ob, imod->srcfile->toChars());
|
||||
ob->writestring(") : ");
|
||||
if (condition->ident)
|
||||
ob->printf("%s\n", condition->ident->toChars());
|
||||
else
|
||||
ob->printf("%d\n", condition->level);
|
||||
}
|
||||
|
||||
|
||||
int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
bool definedInModule = false;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->debugids, ident))
|
||||
{
|
||||
inc = 1;
|
||||
definedInModule = true;
|
||||
}
|
||||
else if (findCondition(global.params.debugids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
@@ -104,6 +129,8 @@ int DebugCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
}
|
||||
else if (level <= global.params.debuglevel || level <= mod->debuglevel)
|
||||
inc = 1;
|
||||
if (!definedInModule)
|
||||
printDepsConditional(sc, this, "depsDebug ");
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
@@ -123,7 +150,7 @@ void VersionCondition::setGlobalLevel(unsigned level)
|
||||
global.params.versionlevel = level;
|
||||
}
|
||||
|
||||
void VersionCondition::checkPredefined(Loc loc, const char *ident)
|
||||
bool VersionCondition::isPredefined(const char *ident)
|
||||
{
|
||||
static const char* reserved[] =
|
||||
{
|
||||
@@ -217,16 +244,12 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
|
||||
for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
|
||||
{
|
||||
if (strcmp(ident, reserved[i]) == 0)
|
||||
goto Lerror;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ident[0] == 'D' && ident[1] == '_')
|
||||
goto Lerror;
|
||||
|
||||
return;
|
||||
|
||||
Lerror:
|
||||
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void VersionCondition::addGlobalIdent(const char *ident)
|
||||
@@ -255,10 +278,14 @@ int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
if (inc == 0)
|
||||
{
|
||||
inc = 2;
|
||||
bool definedInModule=false;
|
||||
if (ident)
|
||||
{
|
||||
if (findCondition(mod->versionids, ident))
|
||||
{
|
||||
inc = 1;
|
||||
definedInModule = true;
|
||||
}
|
||||
else if (findCondition(global.params.versionids, ident))
|
||||
inc = 1;
|
||||
else
|
||||
@@ -270,6 +297,8 @@ int VersionCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
}
|
||||
else if (level <= global.params.versionlevel || level <= mod->versionlevel)
|
||||
inc = 1;
|
||||
if (!definedInModule && (!ident || (!isPredefined(ident->toChars()) && ident != Lexer::idPool(Token::toChars(TOKunittest)) && ident != Lexer::idPool(Token::toChars(TOKassert)))))
|
||||
printDepsConditional(sc, this, "depsVersion ");
|
||||
}
|
||||
return (inc == 1);
|
||||
}
|
||||
@@ -312,9 +341,7 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
{
|
||||
error(loc, (nest > 1000) ? "unresolvable circular static if expression"
|
||||
: "error evaluating static if expression");
|
||||
if (!global.gag)
|
||||
inc = 2; // so we don't see the error message again
|
||||
return 0;
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
if (!sc)
|
||||
@@ -328,21 +355,25 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
sc = sc->push(sc->scopesym);
|
||||
sc->sd = s; // s gets any addMember()
|
||||
sc->flags |= SCOPEstaticif;
|
||||
Expression *e = exp->ctfeSemantic(sc);
|
||||
|
||||
sc = sc->startCTFE();
|
||||
Expression *e = exp->semantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc->endCTFE();
|
||||
|
||||
sc->pop();
|
||||
--nest;
|
||||
|
||||
if (!e->type->checkBoolean())
|
||||
{
|
||||
if (e->type->toBasetype() != Type::terror)
|
||||
exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
|
||||
inc = 0;
|
||||
return 0;
|
||||
goto Lerror;
|
||||
}
|
||||
e = e->ctfeInterpret();
|
||||
--nest;
|
||||
if (e->op == TOKerror)
|
||||
{ exp = e;
|
||||
inc = 0;
|
||||
{
|
||||
goto Lerror;
|
||||
}
|
||||
else if (e->isBool(TRUE))
|
||||
inc = 1;
|
||||
@@ -351,10 +382,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||
else
|
||||
{
|
||||
e->error("expression %s is not constant or does not evaluate to a bool", e->toChars());
|
||||
inc = 2;
|
||||
goto Lerror;
|
||||
}
|
||||
}
|
||||
return (inc == 1);
|
||||
|
||||
Lerror:
|
||||
if (!global.gag)
|
||||
inc = 2; // so we don't see the error message again
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
|
||||
+21
-11
@@ -11,21 +11,22 @@
|
||||
#ifndef DMD_DEBCOND_H
|
||||
#define DMD_DEBCOND_H
|
||||
|
||||
struct Expression;
|
||||
struct Identifier;
|
||||
class Expression;
|
||||
class Identifier;
|
||||
struct OutBuffer;
|
||||
struct Module;
|
||||
class Module;
|
||||
struct Scope;
|
||||
struct ScopeDsymbol;
|
||||
struct DebugCondition;
|
||||
class ScopeDsymbol;
|
||||
class DebugCondition;
|
||||
#include "lexer.h" // dmdhg
|
||||
enum TOK;
|
||||
struct HdrGenState;
|
||||
|
||||
int findCondition(Strings *ids, Identifier *ident);
|
||||
|
||||
struct Condition
|
||||
class Condition
|
||||
{
|
||||
public:
|
||||
Loc loc;
|
||||
int inc; // 0: not computed yet
|
||||
// 1: include
|
||||
@@ -39,8 +40,9 @@ struct Condition
|
||||
virtual DebugCondition *isDebugCondition() { return NULL; }
|
||||
};
|
||||
|
||||
struct DVCondition : Condition
|
||||
class DVCondition : public Condition
|
||||
{
|
||||
public:
|
||||
unsigned level;
|
||||
Identifier *ident;
|
||||
Module *mod;
|
||||
@@ -50,8 +52,9 @@ struct DVCondition : Condition
|
||||
Condition *syntaxCopy();
|
||||
};
|
||||
|
||||
struct DebugCondition : DVCondition
|
||||
class DebugCondition : public DVCondition
|
||||
{
|
||||
public:
|
||||
static void setGlobalLevel(unsigned level);
|
||||
static void addGlobalIdent(const char *ident);
|
||||
|
||||
@@ -62,10 +65,16 @@ struct DebugCondition : DVCondition
|
||||
DebugCondition *isDebugCondition() { return this; }
|
||||
};
|
||||
|
||||
struct VersionCondition : DVCondition
|
||||
class VersionCondition : public DVCondition
|
||||
{
|
||||
public:
|
||||
static void setGlobalLevel(unsigned level);
|
||||
static void checkPredefined(Loc loc, const char *ident);
|
||||
static bool isPredefined(const char *ident);
|
||||
static void checkPredefined(Loc loc, const char *ident)
|
||||
{
|
||||
if (isPredefined(ident))
|
||||
error(loc, "version identifier '%s' is reserved and cannot be set", ident);
|
||||
}
|
||||
static void addGlobalIdent(const char *ident);
|
||||
static void addPredefinedGlobalIdent(const char *ident);
|
||||
|
||||
@@ -75,8 +84,9 @@ struct VersionCondition : DVCondition
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct StaticIfCondition : Condition
|
||||
class StaticIfCondition : public Condition
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
int nest; // limit circular dependencies
|
||||
|
||||
|
||||
+32
-48
@@ -326,11 +326,7 @@ Expression *Mul(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
if (type->isfloating())
|
||||
{ complex_t c;
|
||||
#ifdef IN_GCC
|
||||
real_t r;
|
||||
#else
|
||||
d_float80 r;
|
||||
#endif
|
||||
|
||||
if (e1->type->isreal())
|
||||
{
|
||||
@@ -397,11 +393,7 @@ Expression *Div(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
if (type->isfloating())
|
||||
{ complex_t c;
|
||||
#ifdef IN_GCC
|
||||
real_t r;
|
||||
#else
|
||||
d_float80 r;
|
||||
#endif
|
||||
|
||||
//e1->type->print();
|
||||
//e2->type->print();
|
||||
@@ -486,8 +478,6 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
#ifdef __DMC__
|
||||
c = Port::fmodl(e1->toReal(), r2) + Port::fmodl(e1->toImaginary(), r2) * I;
|
||||
#elif defined(IN_GCC)
|
||||
c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
|
||||
#else
|
||||
c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2));
|
||||
#endif
|
||||
@@ -497,8 +487,6 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
#ifdef __DMC__
|
||||
c = Port::fmodl(e1->toReal(), i2) + Port::fmodl(e1->toImaginary(), i2) * I;
|
||||
#elif defined(IN_GCC)
|
||||
c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
|
||||
#else
|
||||
c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2));
|
||||
#endif
|
||||
@@ -582,8 +570,8 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
|
||||
}
|
||||
else
|
||||
{
|
||||
r = new RealExp(loc, e1->toReal(), Type::tfloat64);
|
||||
v = new RealExp(loc, ldouble(1.0), Type::tfloat64);
|
||||
r = new IntegerExp(loc, e1->toInteger(), e1->type);
|
||||
v = new IntegerExp(loc, 1, e1->type);
|
||||
}
|
||||
|
||||
while (n != 0)
|
||||
@@ -607,7 +595,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
|
||||
// x ^^ y for x < 0 and y not an integer is not defined
|
||||
if (e1->toReal() < 0.0)
|
||||
{
|
||||
e = new RealExp(loc, ldouble(Port::nan), type);
|
||||
e = new RealExp(loc, Port::ldbl_nan, type);
|
||||
}
|
||||
else if (e2->toReal() == 0.5)
|
||||
{
|
||||
@@ -757,7 +745,7 @@ Expression *Xor(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
/* Also returns EXP_CANT_INTERPRET if cannot be computed.
|
||||
*/
|
||||
Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
Loc loc = e1->loc;
|
||||
int cmp;
|
||||
@@ -955,7 +943,7 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
return e;
|
||||
}
|
||||
|
||||
Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
Expression *Identity(TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
{
|
||||
Loc loc = e1->loc;
|
||||
int cmp;
|
||||
@@ -1002,7 +990,7 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
}
|
||||
|
||||
|
||||
Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2)
|
||||
{ Expression *e;
|
||||
Loc loc = e1->loc;
|
||||
dinteger_t n;
|
||||
@@ -1226,7 +1214,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
||||
}
|
||||
|
||||
if (e1->op == TOKarrayliteral && typeb == tb)
|
||||
return e1;
|
||||
return expType(to, e1);
|
||||
|
||||
if (e1->isConst() != 1)
|
||||
return EXP_CANT_INTERPRET;
|
||||
@@ -1333,6 +1321,8 @@ Expression *ArrayLength(Type *type, Expression *e1)
|
||||
|
||||
e = new IntegerExp(loc, dim, type);
|
||||
}
|
||||
else if (e1->type->toBasetype()->ty == Tsarray)
|
||||
e = ((TypeSArray *)e1->type->toBasetype())->dim;
|
||||
else
|
||||
e = EXP_CANT_INTERPRET;
|
||||
return e;
|
||||
@@ -1456,12 +1446,12 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
|
||||
StringExp *es;
|
||||
|
||||
s = mem.malloc((len + 1) * sz);
|
||||
memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz);
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
memcpy((utf8_t *)s, (utf8_t *)es1->string + ilwr * sz, len * sz);
|
||||
memset((utf8_t *)s + len * sz, 0, sz);
|
||||
|
||||
es = new StringExp(loc, s, len, es1->postfix);
|
||||
es->sz = sz;
|
||||
es->committed = 1;
|
||||
es->committed = es1->committed;
|
||||
es->type = type;
|
||||
e = es;
|
||||
}
|
||||
@@ -1499,7 +1489,7 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *n
|
||||
{
|
||||
size_t newlen = newval->len;
|
||||
size_t sz = newval->sz;
|
||||
unsigned char *s = (unsigned char *)newval->string;
|
||||
utf8_t *s = (utf8_t *)newval->string;
|
||||
Type *elemType = existingAE->type->nextOf();
|
||||
for (size_t j = 0; j < newlen; j++)
|
||||
{
|
||||
@@ -1523,7 +1513,7 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *n
|
||||
*/
|
||||
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex)
|
||||
{
|
||||
unsigned char *s = (unsigned char *)existingSE->string;
|
||||
utf8_t *s = (utf8_t *)existingSE->string;
|
||||
for (size_t j = 0; j < newae->elements->dim; j++)
|
||||
{
|
||||
unsigned value = (unsigned)((*newae->elements)[j]->toInteger());
|
||||
@@ -1544,7 +1534,7 @@ void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *n
|
||||
*/
|
||||
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex)
|
||||
{
|
||||
unsigned char *s = (unsigned char *)existingSE->string;
|
||||
utf8_t *s = (utf8_t *)existingSE->string;
|
||||
size_t sz = existingSE->sz;
|
||||
assert(sz == newstr->sz);
|
||||
memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len);
|
||||
@@ -1555,8 +1545,8 @@ void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_
|
||||
*/
|
||||
int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len)
|
||||
{
|
||||
unsigned char *s1 = (unsigned char *)se1->string;
|
||||
unsigned char *s2 = (unsigned char *)se2->string;
|
||||
utf8_t *s1 = (utf8_t *)se1->string;
|
||||
utf8_t *s2 = (utf8_t *)se2->string;
|
||||
size_t sz = se1->sz;
|
||||
assert(sz == se2->sz);
|
||||
|
||||
@@ -1568,11 +1558,9 @@ int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t
|
||||
*/
|
||||
int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len)
|
||||
{
|
||||
unsigned char *s = (unsigned char *)se1->string;
|
||||
utf8_t *s = (utf8_t *)se1->string;
|
||||
size_t sz = se1->sz;
|
||||
|
||||
int c = 0;
|
||||
|
||||
for (size_t j = 0; j < len; j++)
|
||||
{
|
||||
unsigned value = (unsigned)((*ae2->elements)[j + lo2]->toInteger());
|
||||
@@ -1636,13 +1624,13 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
(unsigned char *)&v + (sizeof(dinteger_t) - sz), sz);
|
||||
#endif
|
||||
#else
|
||||
memcpy((unsigned char *)s, &v, sz);
|
||||
memcpy((utf8_t *)s, &v, sz);
|
||||
#endif
|
||||
else
|
||||
utf_encode(sz, s, v);
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
memset((utf8_t *)s + len * sz, 0, sz);
|
||||
|
||||
es = new StringExp(loc, s, len);
|
||||
es->sz = sz;
|
||||
@@ -1696,10 +1684,10 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
}
|
||||
s = mem.malloc((len + 1) * sz);
|
||||
memcpy(s, es1->string, es1->len * sz);
|
||||
memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz);
|
||||
memcpy((utf8_t *)s + es1->len * sz, es2->string, es2->len * sz);
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
memset((utf8_t *)s + len * sz, 0, sz);
|
||||
|
||||
es = new StringExp(loc, s, len);
|
||||
es->sz = sz;
|
||||
@@ -1769,13 +1757,13 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
(unsigned char *)&v + (sizeof(dinteger_t) - sz), sz);
|
||||
#endif
|
||||
#else
|
||||
memcpy((unsigned char *)s + (sz * es1->len), &v, sz);
|
||||
memcpy((utf8_t *)s + (sz * es1->len), &v, sz);
|
||||
#endif
|
||||
else
|
||||
utf_encode(sz, (unsigned char *)s + (sz * es1->len), v);
|
||||
utf_encode(sz, (utf8_t *)s + (sz * es1->len), v);
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
memset((utf8_t *)s + len * sz, 0, sz);
|
||||
|
||||
es = new StringExp(loc, s, len);
|
||||
es->sz = sz;
|
||||
@@ -1802,12 +1790,12 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
(unsigned char *)&v + (sizeof(dinteger_t) - sz), sz);
|
||||
#endif
|
||||
#else
|
||||
memcpy((unsigned char *)s, &v, sz);
|
||||
memcpy((utf8_t *)s, &v, sz);
|
||||
#endif
|
||||
memcpy((unsigned char *)s + sz, es2->string, es2->len * sz);
|
||||
memcpy((utf8_t *)s + sz, es2->string, es2->len * sz);
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
memset((utf8_t *)s + len * sz, 0, sz);
|
||||
|
||||
es = new StringExp(loc, s, len);
|
||||
es->sz = sz;
|
||||
@@ -1828,8 +1816,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
if (type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es1->elements->dim, Type::tindex));
|
||||
e->type = e->type->semantic(loc, NULL);
|
||||
e->type = TypeSArray::makeType(loc, t1->nextOf(), es1->elements->dim);
|
||||
}
|
||||
else
|
||||
e->type = type;
|
||||
@@ -1853,8 +1840,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
if (type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es->elements->dim, Type::tindex));
|
||||
e->type = e->type->semantic(loc, NULL);
|
||||
e->type = TypeSArray::makeType(loc, t1->nextOf(), es->elements->dim);
|
||||
}
|
||||
else
|
||||
e->type = type;
|
||||
@@ -1876,8 +1862,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
if (type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
e->type = new TypeSArray(e2->type, new IntegerExp(loc, es1->elements->dim, Type::tindex));
|
||||
e->type = e->type->semantic(loc, NULL);
|
||||
e->type = TypeSArray::makeType(loc, e2->type, es1->elements->dim);
|
||||
}
|
||||
else
|
||||
e->type = type;
|
||||
@@ -1893,8 +1878,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
||||
|
||||
if (type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
e->type = new TypeSArray(e1->type, new IntegerExp(loc, es2->elements->dim, Type::tindex));
|
||||
e->type = e->type->semantic(loc, NULL);
|
||||
e->type = TypeSArray::makeType(loc, e1->type, es2->elements->dim);
|
||||
}
|
||||
else
|
||||
e->type = type;
|
||||
|
||||
+21
-10
@@ -129,16 +129,24 @@ void cpp_mangle_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
|
||||
buf->writeByte('N');
|
||||
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (!fd)
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (fd && fd->type->isConst())
|
||||
{
|
||||
s->error("C++ static variables not supported");
|
||||
}
|
||||
else if (fd->type->isConst())
|
||||
buf->writeByte('K');
|
||||
|
||||
prefix_name(buf, cms, p);
|
||||
source_name(buf, s);
|
||||
|
||||
}
|
||||
if (vd && !(vd->storage_class & (STCextern | STCgshared)))
|
||||
{
|
||||
s->error("C++ static non- __gshared non-extern variables not supported");
|
||||
}
|
||||
if (vd || fd)
|
||||
{
|
||||
prefix_name(buf, cms, p);
|
||||
source_name(buf, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
buf->writeByte('E');
|
||||
}
|
||||
else
|
||||
@@ -337,7 +345,7 @@ void TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
TypeFunctions for non-static member functions, and non-static
|
||||
member functions of different classes.
|
||||
*/
|
||||
if (!cms->substitute(buf, this))
|
||||
if (!cms->exist(this))
|
||||
{
|
||||
buf->writeByte('F');
|
||||
if (linkage == LINKc)
|
||||
@@ -345,7 +353,10 @@ void TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
next->toCppMangle(buf, cms);
|
||||
Parameter::argsCppMangle(buf, cms, parameters, varargs);
|
||||
buf->writeByte('E');
|
||||
cms->store(this);
|
||||
}
|
||||
else
|
||||
cms->substitute(buf, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -417,7 +428,7 @@ static int argsCppMangleDg(void *ctx, size_t n, Parameter *arg)
|
||||
{
|
||||
ArgsCppMangleCtx *p = (ArgsCppMangleCtx *)ctx;
|
||||
|
||||
Type *t = arg->type;
|
||||
Type *t = arg->type->merge2();
|
||||
if (arg->storageClass & (STCout | STCref))
|
||||
t = t->referenceTo();
|
||||
else if (arg->storageClass & STClazy)
|
||||
|
||||
+11
-14
@@ -30,18 +30,13 @@ struct CtfeStatus
|
||||
static int numAssignments; // total number of assignments executed
|
||||
};
|
||||
|
||||
|
||||
/** Expression subclasses which only exist in CTFE */
|
||||
|
||||
#define TOKclassreference ((TOK)(TOKMAX+1))
|
||||
#define TOKthrownexception ((TOK)(TOKMAX+2))
|
||||
|
||||
/**
|
||||
A reference to a class, or an interface. We need this when we
|
||||
point to a base class (we must record what the type is).
|
||||
*/
|
||||
struct ClassReferenceExp : Expression
|
||||
class ClassReferenceExp : public Expression
|
||||
{
|
||||
public:
|
||||
StructLiteralExp *value;
|
||||
ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
@@ -73,8 +68,9 @@ int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v);
|
||||
|
||||
/** An uninitialized value
|
||||
*/
|
||||
struct VoidInitExp : Expression
|
||||
class VoidInitExp : public Expression
|
||||
{
|
||||
public:
|
||||
VarDeclaration *var;
|
||||
|
||||
VoidInitExp(VarDeclaration *var, Type *type);
|
||||
@@ -86,8 +82,9 @@ struct VoidInitExp : Expression
|
||||
/** Fake class which holds the thrown exception.
|
||||
Used for implementing exception handling.
|
||||
*/
|
||||
struct ThrownExceptionExp : Expression
|
||||
class ThrownExceptionExp : public Expression
|
||||
{
|
||||
public:
|
||||
ClassReferenceExp *thrown; // the thing being tossed
|
||||
ThrownExceptionExp(Loc loc, ClassReferenceExp *victim);
|
||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
||||
@@ -186,11 +183,11 @@ Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e
|
||||
|
||||
/// Return 1 if true, 0 if false
|
||||
/// -1 if comparison is illegal because they point to non-comparable memory blocks
|
||||
int comparePointers(Loc loc, enum TOK op, Type *type, Expression *agg1, dinteger_t ofs1, Expression *agg2, dinteger_t ofs2);
|
||||
int comparePointers(Loc loc, TOK op, Type *type, Expression *agg1, dinteger_t ofs1, Expression *agg2, dinteger_t ofs2);
|
||||
|
||||
// Return eptr op e2, where eptr is a pointer, e2 is an integer,
|
||||
// and op is TOKadd or TOKmin
|
||||
Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
|
||||
Expression *pointerArithmetic(Loc loc, TOK op, Type *type,
|
||||
Expression *eptr, Expression *e2);
|
||||
|
||||
// True if conversion from type 'from' to 'to' involves a reinterpret_cast
|
||||
@@ -235,13 +232,13 @@ void intBinary(TOK op, IntegerExp *dest, Type *type, IntegerExp *e1, IntegerExp
|
||||
bool isCtfeComparable(Expression *e);
|
||||
|
||||
/// Evaluate ==, !=. Resolves slices before comparing. Returns 0 or 1
|
||||
int ctfeEqual(Loc loc, enum TOK op, Expression *e1, Expression *e2);
|
||||
int ctfeEqual(Loc loc, TOK op, Expression *e1, Expression *e2);
|
||||
|
||||
/// Evaluate is, !is. Resolves slices before comparing. Returns 0 or 1
|
||||
int ctfeIdentity(Loc loc, enum TOK op, Expression *e1, Expression *e2);
|
||||
int ctfeIdentity(Loc loc, TOK op, Expression *e1, Expression *e2);
|
||||
|
||||
/// Evaluate >,<=, etc. Resolves slices before comparing. Returns 0 or 1
|
||||
int ctfeCmp(Loc loc, enum TOK op, Expression *e1, Expression *e2);
|
||||
int ctfeCmp(Loc loc, TOK op, Expression *e1, Expression *e2);
|
||||
|
||||
/// Returns e1 ~ e2. Resolves slices before concatenation.
|
||||
Expression *ctfeCat(Type *type, Expression *e1, Expression *e2);
|
||||
|
||||
+200
-69
@@ -156,8 +156,10 @@ char *ThrownExceptionExp::toChars()
|
||||
// Generate an error message when this exception is not caught
|
||||
void ThrownExceptionExp::generateUncaughtError()
|
||||
{
|
||||
thrown->error("Uncaught CTFE exception %s(%s)", thrown->type->toChars(),
|
||||
thrown->value->elements->tdata()[0]->toChars());
|
||||
Expression *e = (*thrown->value->elements)[0];
|
||||
StringExp* se = e->toString();
|
||||
thrown->error("Uncaught CTFE exception %s(%s)", thrown->type->toChars(), se ? se->toChars() : e->toChars());
|
||||
|
||||
/* Also give the line where the throw statement was. We won't have it
|
||||
* in the case where the ThrowStatement is generated internally
|
||||
* (eg, in ScopeStatement)
|
||||
@@ -170,6 +172,8 @@ void ThrownExceptionExp::generateUncaughtError()
|
||||
// True if 'e' is EXP_CANT_INTERPRET, or an exception
|
||||
bool exceptionOrCantInterpret(Expression *e)
|
||||
{
|
||||
assert(EXP_CANT_INTERPRET && "EXP_CANT_INTERPRET must be distinct from "
|
||||
"null, Expression::init not called?");
|
||||
if (e == EXP_CANT_INTERPRET) return true;
|
||||
if (!e || e == EXP_GOTO_INTERPRET || e == EXP_VOID_INTERPRET
|
||||
|| e == EXP_BREAK_INTERPRET || e == EXP_CONTINUE_INTERPRET)
|
||||
@@ -225,7 +229,7 @@ Expressions *copyLiteralArray(Expressions *oldelems)
|
||||
Expressions *newelems = new Expressions();
|
||||
newelems->setDim(oldelems->dim);
|
||||
for (size_t i = 0; i < oldelems->dim; i++)
|
||||
newelems->tdata()[i] = copyLiteral(oldelems->tdata()[i]);
|
||||
(*newelems)[i] = copyLiteral((*oldelems)[i]);
|
||||
return newelems;
|
||||
}
|
||||
|
||||
@@ -236,8 +240,7 @@ Expression *copyLiteral(Expression *e)
|
||||
if (e->op == TOKstring) // syntaxCopy doesn't make a copy for StringExp!
|
||||
{
|
||||
StringExp *se = (StringExp *)e;
|
||||
unsigned char *s;
|
||||
s = (unsigned char *)mem.calloc(se->len + 1, se->sz);
|
||||
utf8_t *s = (utf8_t *)mem.calloc(se->len + 1, se->sz);
|
||||
memcpy(s, se->string, se->len * se->sz);
|
||||
StringExp *se2 = new StringExp(se->loc, s, se->len);
|
||||
se2->committed = se->committed;
|
||||
@@ -277,7 +280,7 @@ Expression *copyLiteral(Expression *e)
|
||||
newelems->setDim(oldelems->dim);
|
||||
for (size_t i = 0; i < newelems->dim; i++)
|
||||
{
|
||||
Expression *m = oldelems->tdata()[i];
|
||||
Expression *m = (*oldelems)[i];
|
||||
// We need the struct definition to detect block assignment
|
||||
AggregateDeclaration *sd = se->sd;
|
||||
Dsymbol *s = sd->fields[i];
|
||||
@@ -297,7 +300,7 @@ Expression *copyLiteral(Expression *e)
|
||||
}
|
||||
else if (v->type->ty != Tarray && v->type->ty!=Taarray) // NOTE: do not copy array references
|
||||
m = copyLiteral(m);
|
||||
newelems->tdata()[i] = m;
|
||||
(*newelems)[i] = m;
|
||||
}
|
||||
#if DMDV2
|
||||
StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems, se->stype);
|
||||
@@ -328,12 +331,12 @@ Expression *copyLiteral(Expression *e)
|
||||
else if (e->op == TOKindex)
|
||||
r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2);
|
||||
else if (e->op == TOKdotvar)
|
||||
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1,
|
||||
((DotVarExp *)e)->var
|
||||
#if DMDV2
|
||||
, ((DotVarExp *)e)->hasOverloads
|
||||
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1,
|
||||
((DotVarExp *)e)->var, ((DotVarExp *)e)->hasOverloads);
|
||||
#else
|
||||
r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var);
|
||||
#endif
|
||||
);
|
||||
else
|
||||
assert(0);
|
||||
r->type = e->type;
|
||||
@@ -348,6 +351,8 @@ Expression *copyLiteral(Expression *e)
|
||||
}
|
||||
else if (e->op == TOKclassreference)
|
||||
return new ClassReferenceExp(e->loc, ((ClassReferenceExp *)e)->value, e->type);
|
||||
else if (e->op == TOKerror)
|
||||
return e;
|
||||
else
|
||||
{
|
||||
e->error("Internal Compiler Error: CTFE literal %s", e->toChars());
|
||||
@@ -364,8 +369,13 @@ Expression *copyLiteral(Expression *e)
|
||||
*/
|
||||
Expression *paintTypeOntoLiteral(Type *type, Expression *lit)
|
||||
{
|
||||
if (lit->type == type)
|
||||
if (lit->type->equals(type))
|
||||
return lit;
|
||||
|
||||
// If it is a cast to inout, retain the original type.
|
||||
if (type->hasWild())
|
||||
return lit;
|
||||
|
||||
Expression *e;
|
||||
if (lit->op == TOKslice)
|
||||
{
|
||||
@@ -455,6 +465,13 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
|
||||
{
|
||||
Expressions *elements = new Expressions();
|
||||
elements->setDim(dim);
|
||||
if (type->ty == Tsarray && type->nextOf()->ty == Tsarray &&
|
||||
elem->type->ty != Tsarray)
|
||||
{
|
||||
// If it is a multidimensional array literal, do it recursively
|
||||
elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem,
|
||||
((TypeSArray *)type->nextOf())->dim->toInteger());
|
||||
}
|
||||
bool mustCopy = needToCopyLiteral(elem);
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ if (mustCopy)
|
||||
@@ -474,8 +491,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type,
|
||||
StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type,
|
||||
unsigned value, size_t dim, int sz)
|
||||
{
|
||||
unsigned char *s;
|
||||
s = (unsigned char *)mem.calloc(dim + 1, sz);
|
||||
utf8_t *s = (utf8_t *)mem.calloc(dim + 1, sz);
|
||||
for (size_t elemi = 0; elemi < dim; ++elemi)
|
||||
{
|
||||
switch (sz)
|
||||
@@ -526,7 +542,7 @@ TypeAArray *toBuiltinAAType(Type *t)
|
||||
assert(sym->ident == Id::AssociativeArray);
|
||||
TemplateInstance *tinst = sym->parent->isTemplateInstance();
|
||||
assert(tinst);
|
||||
return new TypeAArray((Type *)(tinst->tiargs->tdata()[1]), (Type *)(tinst->tiargs->tdata()[0]));
|
||||
return new TypeAArray((Type *)(*tinst->tiargs)[1], (Type *)(*tinst->tiargs)[0]);
|
||||
#else
|
||||
assert(0);
|
||||
return NULL;
|
||||
@@ -539,8 +555,8 @@ TypeAArray *toBuiltinAAType(Type *t)
|
||||
bool isTypeInfo_Class(Type *type)
|
||||
{
|
||||
return type->ty == Tclass &&
|
||||
(( Type::typeinfo == ((TypeClass*)type)->sym)
|
||||
|| Type::typeinfo->isBaseOf(((TypeClass*)type)->sym, NULL));
|
||||
(( Type::dtypeinfo == ((TypeClass*)type)->sym)
|
||||
|| Type::dtypeinfo->isBaseOf(((TypeClass*)type)->sym, NULL));
|
||||
}
|
||||
|
||||
/************** Pointer operations ************************************/
|
||||
@@ -564,20 +580,36 @@ int isTrueBool(Expression *e)
|
||||
* destPointee may be void.
|
||||
*/
|
||||
bool isSafePointerCast(Type *srcPointee, Type *destPointee)
|
||||
{ // It's OK if both are the same (modulo const)
|
||||
{
|
||||
// It's safe to cast S** to D** if it's OK to cast S* to D*
|
||||
while (srcPointee->ty == Tpointer && destPointee->ty == Tpointer)
|
||||
{
|
||||
srcPointee = srcPointee->nextOf();
|
||||
destPointee = destPointee->nextOf();
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
if (srcPointee->castMod(0) == destPointee->castMod(0))
|
||||
return true;
|
||||
#else
|
||||
// It's OK if both are the same (modulo const)
|
||||
srcPointee = srcPointee->castMod(0);
|
||||
destPointee = destPointee->castMod(0);
|
||||
#endif
|
||||
if (srcPointee == destPointee)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
// It's OK if function pointers differ only in safe/pure/nothrow
|
||||
if (srcPointee->ty == Tfunction && destPointee->ty == Tfunction)
|
||||
return srcPointee->covariant(destPointee) == 1;
|
||||
|
||||
// it's OK to cast to void*
|
||||
if (destPointee->ty == Tvoid)
|
||||
return true;
|
||||
// It's OK if they are the same size integers, eg int* and uint*
|
||||
return srcPointee->isintegral() && destPointee->isintegral()
|
||||
&& srcPointee->size() == destPointee->size();
|
||||
|
||||
// It's OK if they are the same size (static array of) integers, eg:
|
||||
// int* --> uint*
|
||||
// int[5][] --> uint[5][]
|
||||
return srcPointee->baseElemOf()->isintegral() &&
|
||||
destPointee->baseElemOf()->isintegral() &&
|
||||
srcPointee->size() == destPointee->size();
|
||||
}
|
||||
|
||||
Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs)
|
||||
@@ -599,7 +631,7 @@ Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs)
|
||||
i = ((ClassReferenceExp *)ex)->getFieldIndex(e->type, v->offset);
|
||||
else
|
||||
i = se->getFieldIndex(e->type, v->offset);
|
||||
e = se->elements->tdata()[i];
|
||||
e = (*se->elements)[i];
|
||||
}
|
||||
if (e->op == TOKindex)
|
||||
{
|
||||
@@ -669,7 +701,7 @@ Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e
|
||||
|
||||
// Return eptr op e2, where eptr is a pointer, e2 is an integer,
|
||||
// and op is TOKadd or TOKmin
|
||||
Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
|
||||
Expression *pointerArithmetic(Loc loc, TOK op, Type *type,
|
||||
Expression *eptr, Expression *e2)
|
||||
{
|
||||
if (eptr->type->nextOf()->ty == Tvoid)
|
||||
@@ -749,14 +781,12 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
|
||||
|
||||
// Return 1 if true, 0 if false
|
||||
// -1 if comparison is illegal because they point to non-comparable memory blocks
|
||||
int comparePointers(Loc loc, enum TOK op, Type *type, Expression *agg1, dinteger_t ofs1,
|
||||
int comparePointers(Loc loc, TOK op, Type *type, Expression *agg1, dinteger_t ofs1,
|
||||
Expression *agg2, dinteger_t ofs2)
|
||||
{
|
||||
if ( pointToSameMemoryBlock(agg1, agg2) )
|
||||
{
|
||||
dinteger_t cm = ofs1 - ofs2;
|
||||
dinteger_t n;
|
||||
dinteger_t zero = 0;
|
||||
switch(op)
|
||||
{
|
||||
case TOKlt: n = (ofs1 < ofs2); break;
|
||||
@@ -790,6 +820,8 @@ int comparePointers(Loc loc, enum TOK op, Type *type, Expression *agg1, dinteger
|
||||
case TOKnotequal:
|
||||
cmp = (null1 == null2);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -844,7 +876,7 @@ Expression *paintFloatInt(Expression *fromVal, Type *to)
|
||||
if (to->isintegral())
|
||||
{
|
||||
u.f = fromVal->toReal();
|
||||
return new IntegerExp(fromVal->loc, ldouble(u.x), to);
|
||||
return new IntegerExp(fromVal->loc, (dinteger_t)ldouble(u.x), to);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -887,6 +919,9 @@ void intUnary(TOK op, IntegerExp *e)
|
||||
case TOKtilde:
|
||||
e->value = ~e->value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,6 +1124,8 @@ bool isCtfeComparable(Expression *e)
|
||||
if (x->isConst() != 1 &&
|
||||
x->op != TOKnull &&
|
||||
x->op != TOKstring &&
|
||||
x->op != TOKfunction &&
|
||||
x->op != TOKdelegate &&
|
||||
x->op != TOKarrayliteral &&
|
||||
x->op != TOKstructliteral &&
|
||||
x->op != TOKclassreference)
|
||||
@@ -1244,16 +1281,16 @@ int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len)
|
||||
{ lo1 = ((SliceExp *)x)->lwr->toInteger();
|
||||
x = ((SliceExp*)x)->e1;
|
||||
}
|
||||
StringExp *se1 = (x->op == TOKstring) ? (StringExp *)x : 0;
|
||||
ArrayLiteralExp *ae1 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : 0;
|
||||
StringExp *se1 = (x->op == TOKstring) ? (StringExp *)x : NULL;
|
||||
ArrayLiteralExp *ae1 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : NULL;
|
||||
|
||||
x = e2;
|
||||
if (x->op == TOKslice)
|
||||
{ lo2 = ((SliceExp *)x)->lwr->toInteger();
|
||||
x = ((SliceExp*)x)->e1;
|
||||
}
|
||||
StringExp *se2 = (x->op == TOKstring) ? (StringExp *)x : 0;
|
||||
ArrayLiteralExp *ae2 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : 0;
|
||||
StringExp *se2 = (x->op == TOKstring) ? (StringExp *)x : NULL;
|
||||
ArrayLiteralExp *ae2 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : NULL;
|
||||
|
||||
// Now both must be either TOKarrayliteral or TOKstring
|
||||
if (se1 && se2)
|
||||
@@ -1286,6 +1323,21 @@ int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Given a delegate expression e, return .funcptr.
|
||||
* If e is NullExp, return NULL.
|
||||
*/
|
||||
FuncDeclaration *funcptrOf(Expression *e)
|
||||
{
|
||||
assert(e->type->ty == Tdelegate);
|
||||
|
||||
if (e->op == TOKdelegate)
|
||||
return ((DelegateExp *)e)->func;
|
||||
if (e->op == TOKfunction)
|
||||
return ((FuncExp *)e)->fd;
|
||||
assert(e->op == TOKnull);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool isArray(Expression *e)
|
||||
{
|
||||
return e->op == TOKarrayliteral || e->op == TOKstring ||
|
||||
@@ -1303,13 +1355,16 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// null == null, regardless of type
|
||||
|
||||
if (e1->op == TOKnull && e2->op == TOKnull)
|
||||
return 0;
|
||||
|
||||
if (e1->type->ty == Tpointer && e2->type->ty == Tpointer)
|
||||
{ // Can only be an equality test.
|
||||
if (e1->op == TOKnull && e2->op == TOKnull)
|
||||
return 0;
|
||||
{
|
||||
// Can only be an equality test.
|
||||
|
||||
dinteger_t ofs1, ofs2;
|
||||
Expression *agg1 = getAggregateFromPointer(e1, &ofs1);
|
||||
Expression *agg2 = getAggregateFromPointer(e2, &ofs2);
|
||||
@@ -1320,6 +1375,35 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (e1->type->ty == Tdelegate && e2->type->ty == Tdelegate)
|
||||
{
|
||||
// If .funcptr isn't the same, they are not equal
|
||||
|
||||
if (funcptrOf(e1) != funcptrOf(e2))
|
||||
return 1;
|
||||
|
||||
// If both are delegate literals, assume they have the
|
||||
// same closure pointer. TODO: We don't support closures yet!
|
||||
if (e1->op == TOKfunction && e2->op == TOKfunction)
|
||||
return 0;
|
||||
assert(e1->op == TOKdelegate && e2->op == TOKdelegate);
|
||||
|
||||
// Same .funcptr. Do they have the same .ptr?
|
||||
Expression * ptr1 = ((DelegateExp *)e1)->e1;
|
||||
Expression * ptr2 = ((DelegateExp *)e2)->e1;
|
||||
|
||||
dinteger_t ofs1, ofs2;
|
||||
Expression *agg1 = getAggregateFromPointer(ptr1, &ofs1);
|
||||
Expression *agg2 = getAggregateFromPointer(ptr2, &ofs2);
|
||||
// If they are TOKvar, it means they are FuncDeclarations
|
||||
if ((agg1 == agg2 && ofs1 == ofs2) ||
|
||||
(agg1->op == TOKvar && agg2->op == TOKvar &&
|
||||
((VarExp *)agg1)->var == ((VarExp *)agg2)->var))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (isArray(e1) && isArray(e2))
|
||||
{
|
||||
uinteger_t len1 = resolveArrayLength(e1);
|
||||
@@ -1409,7 +1493,7 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2)
|
||||
|
||||
|
||||
/// Evaluate ==, !=. Resolves slices before comparing. Returns 0 or 1
|
||||
int ctfeEqual(Loc loc, enum TOK op, Expression *e1, Expression *e2)
|
||||
int ctfeEqual(Loc loc, TOK op, Expression *e1, Expression *e2)
|
||||
{
|
||||
int cmp = !ctfeRawCmp(loc, e1, e2);
|
||||
if (op == TOKnotequal)
|
||||
@@ -1419,7 +1503,7 @@ int ctfeEqual(Loc loc, enum TOK op, Expression *e1, Expression *e2)
|
||||
|
||||
|
||||
/// Evaluate is, !is. Resolves slices before comparing. Returns 0 or 1
|
||||
int ctfeIdentity(Loc loc, enum TOK op, Expression *e1, Expression *e2)
|
||||
int ctfeIdentity(Loc loc, TOK op, Expression *e1, Expression *e2)
|
||||
{
|
||||
int cmp;
|
||||
if (e1->op == TOKnull)
|
||||
@@ -1456,7 +1540,7 @@ int ctfeIdentity(Loc loc, enum TOK op, Expression *e1, Expression *e2)
|
||||
|
||||
|
||||
/// Evaluate >,<=, etc. Resolves slices before comparing. Returns 0 or 1
|
||||
int ctfeCmp(Loc loc, enum TOK op, Expression *e1, Expression *e2)
|
||||
int ctfeCmp(Loc loc, TOK op, Expression *e1, Expression *e2)
|
||||
{
|
||||
int n;
|
||||
Type *t1 = e1->type->toBasetype();
|
||||
@@ -1522,7 +1606,8 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||
void *s = mem.malloc((len + 1) * sz);
|
||||
memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz);
|
||||
for (size_t i = 0; i < es2->elements->dim; i++)
|
||||
{ Expression *es2e = es2->elements->tdata()[i];
|
||||
{
|
||||
Expression *es2e = (*es2->elements)[i];
|
||||
if (es2e->op != TOKint64)
|
||||
return EXP_CANT_INTERPRET;
|
||||
dinteger_t v = es2e->toInteger();
|
||||
@@ -1534,12 +1619,12 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||
(unsigned char *)&v + (sizeof(dinteger_t) - sz), sz);
|
||||
#endif
|
||||
#else
|
||||
memcpy((unsigned char *)s + i * sz, &v, sz);
|
||||
memcpy((utf8_t *)s + i * sz, &v, sz);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
memset((utf8_t *)s + len * sz, 0, sz);
|
||||
|
||||
StringExp *es = new StringExp(loc, s, len);
|
||||
es->sz = sz;
|
||||
@@ -1561,7 +1646,8 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||
void *s = mem.malloc((len + 1) * sz);
|
||||
memcpy(s, es1->string, es1->len * sz);
|
||||
for (size_t i = 0; i < es2->elements->dim; i++)
|
||||
{ Expression *es2e = es2->elements->tdata()[i];
|
||||
{
|
||||
Expression *es2e = (*es2->elements)[i];
|
||||
if (es2e->op != TOKint64)
|
||||
return EXP_CANT_INTERPRET;
|
||||
dinteger_t v = es2e->toInteger();
|
||||
@@ -1573,12 +1659,12 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||
(unsigned char *) &v + (sizeof(dinteger_t) - sz), sz);
|
||||
#endif
|
||||
#else
|
||||
memcpy((unsigned char *)s + (es1->len + i) * sz, &v, sz);
|
||||
memcpy((utf8_t *)s + (es1->len + i) * sz, &v, sz);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Add terminating 0
|
||||
memset((unsigned char *)s + len * sz, 0, sz);
|
||||
memset((utf8_t *)s + len * sz, 0, sz);
|
||||
|
||||
StringExp *es = new StringExp(loc, s, len);
|
||||
es->sz = sz;
|
||||
@@ -1587,6 +1673,32 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||
e = es;
|
||||
return e;
|
||||
}
|
||||
else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
|
||||
t1->nextOf()->equals(t2->nextOf()))
|
||||
{
|
||||
// [ e1 ] ~ [ e2 ] ---> [ e1, e2 ]
|
||||
ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
|
||||
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
|
||||
|
||||
es1 = new ArrayLiteralExp(es1->loc, copyLiteralArray(es1->elements));
|
||||
es1->elements->insert(es1->elements->dim, copyLiteralArray(es2->elements));
|
||||
e = es1;
|
||||
e->type = type;
|
||||
return e;
|
||||
}
|
||||
else if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
|
||||
t1->nextOf()->equals(t2->nextOf()))
|
||||
{
|
||||
// [ e1 ] ~ null ----> [ e1 ].dup
|
||||
return paintTypeOntoLiteral(type, copyLiteral(e1));
|
||||
}
|
||||
else if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
|
||||
t1->nextOf()->equals(t2->nextOf()))
|
||||
{
|
||||
// null ~ [ e2 ] ----> [ e2 ].dup
|
||||
return paintTypeOntoLiteral(type, copyLiteral(e2));
|
||||
}
|
||||
|
||||
return Cat(type, e1, e2);
|
||||
}
|
||||
|
||||
@@ -1600,11 +1712,11 @@ Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2)
|
||||
for (size_t i = ae->keys->dim; i;)
|
||||
{
|
||||
i--;
|
||||
Expression *ekey = ae->keys->tdata()[i];
|
||||
Expression *ekey = (*ae->keys)[i];
|
||||
int eq = ctfeEqual(loc, TOKequal, ekey, e2);
|
||||
if (eq)
|
||||
{
|
||||
return ae->values->tdata()[i];
|
||||
return (*ae->values)[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -1634,7 +1746,7 @@ Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx)
|
||||
error(loc, "array index %llu is out of bounds %s[0 .. %llu]", indx, e1->toChars(), (ulonglong)ale->elements->dim);
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
Expression *e = ale->elements->tdata()[indx];
|
||||
Expression *e = (*ale->elements)[indx];
|
||||
return paintTypeOntoLiteral(type, e);
|
||||
}
|
||||
|
||||
@@ -1654,7 +1766,12 @@ Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e)
|
||||
// Allow TypeInfo type painting
|
||||
if (isTypeInfo_Class(e->type) && e->type->implicitConvTo(to))
|
||||
return paintTypeOntoLiteral(to, e);
|
||||
|
||||
#if DMDV2
|
||||
// Allow casting away const for struct literals
|
||||
if (e->op == TOKstructliteral &&
|
||||
e->type->toBasetype()->castMod(0) == to->toBasetype()->castMod(0))
|
||||
return paintTypeOntoLiteral(to, e);
|
||||
#endif
|
||||
Expression *r = Cast(type, to, e);
|
||||
if (r == EXP_CANT_INTERPRET)
|
||||
error(loc, "cannot cast %s to %s at compile time", e->toChars(), to->toChars());
|
||||
@@ -1711,8 +1828,8 @@ void assignInPlace(Expression *dest, Expression *src)
|
||||
|
||||
for (size_t i= 0; i < oldelems->dim; ++i)
|
||||
{
|
||||
Expression *e = newelems->tdata()[i];
|
||||
Expression *o = oldelems->tdata()[i];
|
||||
Expression *e = (*newelems)[i];
|
||||
Expression *o = (*oldelems)[i];
|
||||
if (e->op == TOKstructliteral)
|
||||
{
|
||||
assert(o->op == e->op);
|
||||
@@ -1724,7 +1841,7 @@ void assignInPlace(Expression *dest, Expression *src)
|
||||
}
|
||||
else
|
||||
{
|
||||
oldelems->tdata()[i] = newelems->tdata()[i];
|
||||
(*oldelems)[i] = (*newelems)[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1734,10 +1851,10 @@ void recursiveBlockAssign(ArrayLiteralExp *ae, Expression *val, bool wantRef)
|
||||
assert( ae->type->ty == Tsarray || ae->type->ty == Tarray);
|
||||
#if DMDV2
|
||||
Type *desttype = ((TypeArray *)ae->type)->next->castMod(0);
|
||||
bool directblk = (val->type->toBasetype()->castMod(0)) == desttype;
|
||||
bool directblk = (val->type->toBasetype()->castMod(0))->equals(desttype);
|
||||
#else
|
||||
Type *desttype = ((TypeArray *)ae->type)->next;
|
||||
bool directblk = (val->type->toBasetype()) == desttype;
|
||||
bool directblk = (val->type->toBasetype())->equals(desttype);
|
||||
#endif
|
||||
|
||||
bool cow = !(val->op == TOKstructliteral || val->op == TOKarrayliteral
|
||||
@@ -1745,16 +1862,16 @@ void recursiveBlockAssign(ArrayLiteralExp *ae, Expression *val, bool wantRef)
|
||||
|
||||
for (size_t k = 0; k < ae->elements->dim; k++)
|
||||
{
|
||||
if (!directblk && ae->elements->tdata()[k]->op == TOKarrayliteral)
|
||||
if (!directblk && (*ae->elements)[k]->op == TOKarrayliteral)
|
||||
{
|
||||
recursiveBlockAssign((ArrayLiteralExp *)ae->elements->tdata()[k], val, wantRef);
|
||||
recursiveBlockAssign((ArrayLiteralExp *)(*ae->elements)[k], val, wantRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wantRef || cow)
|
||||
ae->elements->tdata()[k] = val;
|
||||
(*ae->elements)[k] = val;
|
||||
else
|
||||
assignInPlace(ae->elements->tdata()[k], val);
|
||||
assignInPlace((*ae->elements)[k], val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1770,7 +1887,7 @@ Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expre
|
||||
if (j == indexToChange)
|
||||
(*expsx)[j] = newelem;
|
||||
else
|
||||
(*expsx)[j] = oldelems->tdata()[j];
|
||||
(*expsx)[j] = (*oldelems)[j];
|
||||
}
|
||||
return expsx;
|
||||
}
|
||||
@@ -1801,10 +1918,11 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae,
|
||||
int updated = 0;
|
||||
for (size_t j = valuesx->dim; j; )
|
||||
{ j--;
|
||||
Expression *ekey = aae->keys->tdata()[j];
|
||||
Expression *ekey = (*aae->keys)[j];
|
||||
int eq = ctfeEqual(loc, TOKequal, ekey, index);
|
||||
if (eq)
|
||||
{ valuesx->tdata()[j] = newval;
|
||||
{
|
||||
(*valuesx)[j] = newval;
|
||||
updated = 1;
|
||||
}
|
||||
}
|
||||
@@ -1838,7 +1956,7 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
|
||||
if (oldval->op == TOKstring)
|
||||
{
|
||||
StringExp *oldse = (StringExp *)oldval;
|
||||
unsigned char *s = (unsigned char *)mem.calloc(newlen + 1, oldse->sz);
|
||||
utf8_t *s = (utf8_t *)mem.calloc(newlen + 1, oldse->sz);
|
||||
memcpy(s, oldse->string, copylen * oldse->sz);
|
||||
unsigned defaultValue = (unsigned)(defaultElem->toInteger());
|
||||
for (size_t elemi = copylen; elemi < newlen; ++elemi)
|
||||
@@ -1890,11 +2008,12 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
|
||||
|
||||
bool isCtfeValueValid(Expression *newval)
|
||||
{
|
||||
if (
|
||||
#if DMDV2
|
||||
newval->type->ty == Tnull ||
|
||||
bool isnull = newval->type->ty == Tnull;
|
||||
#else
|
||||
bool isnull = false;
|
||||
#endif
|
||||
isPointer(newval->type) )
|
||||
if (isnull || isPointer(newval->type))
|
||||
{
|
||||
if (newval->op == TOKaddress || newval->op == TOKnull ||
|
||||
newval->op == TOKstring)
|
||||
@@ -1946,8 +2065,19 @@ bool isCtfeValueValid(Expression *newval)
|
||||
if (ie->e2->op == TOKvar)
|
||||
return true;
|
||||
}
|
||||
if (newval->op == TOKfunction) return true; // function/delegate literal
|
||||
if (newval->op == TOKdelegate) return true;
|
||||
|
||||
if (newval->op == TOKfunction)
|
||||
return true; // function literal or delegate literal
|
||||
|
||||
if (newval->op == TOKdelegate)
|
||||
{
|
||||
Expression *dge = ((DelegateExp *)newval)->e1;
|
||||
if (dge->op == TOKvar && ((VarExp *)dge)->var->isFuncDeclaration())
|
||||
return true; // &nestedfunc
|
||||
|
||||
if (dge->op == TOKstructliteral || dge->op == TOKclassreference)
|
||||
return true; // &struct.func or &clasinst.func
|
||||
}
|
||||
if (newval->op == TOKsymoff) // function pointer
|
||||
{
|
||||
if (((SymOffExp *)newval)->var->isFuncDeclaration())
|
||||
@@ -1955,6 +2085,7 @@ bool isCtfeValueValid(Expression *newval)
|
||||
if (((SymOffExp *)newval)->var->isDataseg())
|
||||
return true; // pointer to static variable
|
||||
}
|
||||
|
||||
if (newval->op == TOKint64 || newval->op == TOKfloat64 ||
|
||||
newval->op == TOKchar || newval->op == TOKcomplex80)
|
||||
return true;
|
||||
|
||||
+152
-144
@@ -102,27 +102,27 @@ unsigned Declaration::size(Loc loc)
|
||||
return type->size();
|
||||
}
|
||||
|
||||
int Declaration::isDelete()
|
||||
bool Declaration::isDelete()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Declaration::isDataseg()
|
||||
bool Declaration::isDataseg()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Declaration::isThreadlocal()
|
||||
bool Declaration::isThreadlocal()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Declaration::isCodeseg()
|
||||
bool Declaration::isCodeseg()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
enum PROT Declaration::prot()
|
||||
PROT Declaration::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
@@ -148,7 +148,7 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int fl
|
||||
{
|
||||
const char *s = isParameter() && parent->ident != Id::ensure ? "parameter" : "result";
|
||||
if (!flag) error(loc, "cannot modify %s '%s' in contract", s, toChars());
|
||||
return 0;
|
||||
return 2; // do not report type related errors
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
|
||||
this->loc = loc;
|
||||
this->type = NULL;
|
||||
this->objects = objects;
|
||||
this->isexp = 0;
|
||||
this->isexp = false;
|
||||
this->tupletype = NULL;
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ Type *TupleDeclaration::getType()
|
||||
/* It's only a type tuple if all the Object's are types
|
||||
*/
|
||||
for (size_t i = 0; i < objects->dim; i++)
|
||||
{ Object *o = (*objects)[i];
|
||||
{ RootObject *o = (*objects)[i];
|
||||
|
||||
if (o->dyncast() != DYNCAST_TYPE)
|
||||
{
|
||||
@@ -253,11 +253,11 @@ Type *TupleDeclaration::getType()
|
||||
return tupletype;
|
||||
}
|
||||
|
||||
int TupleDeclaration::needThis()
|
||||
bool TupleDeclaration::needThis()
|
||||
{
|
||||
//printf("TupleDeclaration::needThis(%s)\n", toChars());
|
||||
for (size_t i = 0; i < objects->dim; i++)
|
||||
{ Object *o = (*objects)[i];
|
||||
{ RootObject *o = (*objects)[i];
|
||||
if (o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{ Expression *e = (Expression *)o;
|
||||
if (e->op == TOKdsymbol)
|
||||
@@ -265,12 +265,12 @@ int TupleDeclaration::needThis()
|
||||
Declaration *d = ve->s->isDeclaration();
|
||||
if (d && d->needThis())
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if IN_LLVM
|
||||
@@ -279,7 +279,7 @@ void TupleDeclaration::semantic3(Scope *sc)
|
||||
{
|
||||
//printf("TupleDeclaration::semantic3((%s)\n", toChars());
|
||||
for (size_t i = 0; i < objects->dim; i++)
|
||||
{ Object *o = (Object *)objects->data[i];
|
||||
{ RootObject *o = (RootObject *)objects->data[i];
|
||||
if (o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{ Expression *e = (Expression *)o;
|
||||
if (e->op == TOKdsymbol)
|
||||
@@ -445,7 +445,7 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
|
||||
this->htype = NULL;
|
||||
this->haliassym = NULL;
|
||||
this->overnext = NULL;
|
||||
this->inSemantic = 0;
|
||||
this->inSemantic = false;
|
||||
assert(type);
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
|
||||
this->htype = NULL;
|
||||
this->haliassym = NULL;
|
||||
this->overnext = NULL;
|
||||
this->inSemantic = 0;
|
||||
this->inSemantic = false;
|
||||
assert(s);
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
aliassym->semantic(sc);
|
||||
return;
|
||||
}
|
||||
this->inSemantic = 1;
|
||||
this->inSemantic = true;
|
||||
|
||||
#if DMDV1 // don't really know why this is here
|
||||
if (storage_class & STCconst)
|
||||
@@ -587,7 +587,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
if (overnext)
|
||||
ScopeDsymbol::multiplyDefined(Loc(), overnext, this);
|
||||
this->inSemantic = 0;
|
||||
this->inSemantic = false;
|
||||
|
||||
if (global.gag && errors != global.errors)
|
||||
type = savedtype;
|
||||
@@ -641,16 +641,16 @@ void AliasDeclaration::semantic(Scope *sc)
|
||||
type = savedtype;
|
||||
overnext = savedovernext;
|
||||
aliassym = NULL;
|
||||
inSemantic = 0;
|
||||
inSemantic = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
//printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars());
|
||||
aliassym = s;
|
||||
this->inSemantic = 0;
|
||||
this->inSemantic = false;
|
||||
}
|
||||
|
||||
int AliasDeclaration::overloadInsert(Dsymbol *s)
|
||||
bool AliasDeclaration::overloadInsert(Dsymbol *s)
|
||||
{
|
||||
/* Don't know yet what the aliased symbol is, so assume it can
|
||||
* be overloaded and check later for correctness.
|
||||
@@ -673,10 +673,10 @@ int AliasDeclaration::overloadInsert(Dsymbol *s)
|
||||
{
|
||||
if (s == this)
|
||||
{
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
overnext = s;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -702,7 +702,13 @@ Dsymbol *AliasDeclaration::toAlias()
|
||||
assert(this != aliassym);
|
||||
//static int count; if (++count == 10) *(char*)0=0;
|
||||
if (inSemantic)
|
||||
{ error("recursive alias declaration");
|
||||
{
|
||||
error("recursive alias declaration");
|
||||
|
||||
// Avoid breaking "recursive alias" state during errors gagged
|
||||
if (global.isSpeculativeGagging())
|
||||
return this;
|
||||
|
||||
aliassym = new AliasDeclaration(loc, ident, Type::terror);
|
||||
type = Type::terror;
|
||||
}
|
||||
@@ -858,6 +864,9 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
// return;
|
||||
// sem = SemanticIn;
|
||||
|
||||
if (sem >= SemanticDone)
|
||||
return;
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
@@ -885,8 +894,8 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
|
||||
// Infering the type requires running semantic,
|
||||
// so mark the scope as ctfe if required
|
||||
if (storage_class & (STCmanifest | STCstatic))
|
||||
sc->needctfe++;
|
||||
bool needctfe = (storage_class & (STCmanifest | STCstatic));
|
||||
if (needctfe) sc = sc->startCTFE();
|
||||
|
||||
//printf("inferring type for %s with init %s\n", toChars(), init->toChars());
|
||||
ArrayInitializer *ai = init->isArrayInitializer();
|
||||
@@ -907,10 +916,11 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
type = type->nextOf()->arrayOf();
|
||||
}
|
||||
else
|
||||
{
|
||||
type = init->inferType(sc);
|
||||
}
|
||||
|
||||
if (storage_class & (STCmanifest | STCstatic))
|
||||
sc->needctfe--;
|
||||
if (needctfe) sc = sc->endCTFE();
|
||||
// type = type->semantic(loc, sc);
|
||||
|
||||
inuse--;
|
||||
@@ -986,9 +996,7 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
FuncDeclaration *fd = parent->isFuncDeclaration();
|
||||
|
||||
Type *tb = type->toBasetype();
|
||||
Type *tbn = tb;
|
||||
while (tbn->ty == Tsarray)
|
||||
tbn = tbn->nextOf()->toBasetype();
|
||||
Type *tbn = tb->baseElemOf();
|
||||
if (tb->ty == Tvoid && !(storage_class & STClazy))
|
||||
{
|
||||
if (inferred)
|
||||
@@ -1128,7 +1136,8 @@ Lnomatch:
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nelems; i++)
|
||||
{ Parameter *arg = Parameter::getNth(tt->arguments, i);
|
||||
{
|
||||
Parameter *arg = Parameter::getNth(tt->arguments, i);
|
||||
|
||||
OutBuffer buf;
|
||||
buf.printf("_%s_field_%llu", ident->toChars(), (ulonglong)i);
|
||||
@@ -1136,20 +1145,24 @@ Lnomatch:
|
||||
const char *name = (const char *)buf.extractData();
|
||||
Identifier *id = Lexer::idPool(name);
|
||||
|
||||
Expression *einit = ie;
|
||||
if (ie && ie->op == TOKtuple)
|
||||
Initializer *ti;
|
||||
if (ie)
|
||||
{
|
||||
TupleExp *te = (TupleExp *)ie;
|
||||
einit = (*te->exps)[i];
|
||||
if (i == 0)
|
||||
einit = Expression::combine(te->e0, einit);
|
||||
}
|
||||
Initializer *ti = init;
|
||||
if (einit)
|
||||
{ ti = new ExpInitializer(einit->loc, einit);
|
||||
Expression *einit = ie;
|
||||
if (ie->op == TOKtuple)
|
||||
{
|
||||
TupleExp *te = (TupleExp *)ie;
|
||||
einit = (*te->exps)[i];
|
||||
if (i == 0)
|
||||
einit = Expression::combine(te->e0, einit);
|
||||
}
|
||||
ti = new ExpInitializer(einit->loc, einit);
|
||||
}
|
||||
else
|
||||
ti = init ? init->syntaxCopy() : NULL;
|
||||
|
||||
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
|
||||
v->storage_class |= storage_class;
|
||||
if (arg->storageClass & STCparameter)
|
||||
v->storage_class |= arg->storageClass;
|
||||
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
|
||||
@@ -1169,7 +1182,7 @@ Lnomatch:
|
||||
}
|
||||
TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps);
|
||||
v2->parent = this->parent;
|
||||
v2->isexp = 1;
|
||||
v2->isexp = true;
|
||||
aliassym = v2;
|
||||
return;
|
||||
}
|
||||
@@ -1227,8 +1240,17 @@ Lnomatch:
|
||||
{
|
||||
const char *p = loc.toChars();
|
||||
const char *s = (storage_class & STCimmutable) ? "immutable" : "const";
|
||||
fprintf(stderr, "%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;
|
||||
#if DMDV2
|
||||
if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor ||
|
||||
tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor)
|
||||
{
|
||||
if (!isThisDeclaration())
|
||||
aad->noDefaultCtor = TRUE;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (storage_class & (STCconst | STCimmutable) && init)
|
||||
{
|
||||
@@ -1239,15 +1261,18 @@ Lnomatch:
|
||||
storage_class |= STCstatic;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
storage_class |= STCfield;
|
||||
#if DMDV2
|
||||
if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor ||
|
||||
tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor)
|
||||
aad->noDefaultCtor = TRUE;
|
||||
if ((tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor) ||
|
||||
(tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor))
|
||||
{
|
||||
if (!isThisDeclaration())
|
||||
aad->noDefaultCtor = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
InterfaceDeclaration *id = parent->isInterfaceDeclaration();
|
||||
@@ -1300,25 +1325,35 @@ Lnomatch:
|
||||
{
|
||||
if (func->fes)
|
||||
func = func->fes->func;
|
||||
if (!((TypeFunction *)func->type)->iswild)
|
||||
bool isWild = false;
|
||||
for (FuncDeclaration *fd = func; fd; fd = fd->toParent2()->isFuncDeclaration())
|
||||
{
|
||||
if (((TypeFunction *)fd->type)->iswild)
|
||||
{
|
||||
isWild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isWild)
|
||||
{
|
||||
error("inout variables can only be declared inside inout functions");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(storage_class & (STCctfe | STCref)) && tbn->ty == Tstruct &&
|
||||
if (!(storage_class & (STCctfe | STCref | STCresult)) && tbn->ty == Tstruct &&
|
||||
((TypeStruct *)tbn)->sym->noDefaultCtor)
|
||||
{
|
||||
if (!init)
|
||||
{ if (isField())
|
||||
{
|
||||
if (isField())
|
||||
/* For fields, we'll check the constructor later to make sure it is initialized
|
||||
*/
|
||||
storage_class |= STCnodefaultctor;
|
||||
else if (storage_class & STCparameter)
|
||||
;
|
||||
else
|
||||
error("initializer required for type %s", type->toChars());
|
||||
error("default construction is disabled for type %s", type->toChars());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1347,7 +1382,7 @@ Lnomatch:
|
||||
else if (storage_class & STCmanifest)
|
||||
error("manifest constants must have initializers");
|
||||
|
||||
enum TOK op = TOKconstruct;
|
||||
TOK op = TOKconstruct;
|
||||
if (!init && !sc->inunion && !(storage_class & (STCstatic | STCgshared | STCextern)) && fd &&
|
||||
(!(storage_class & (STCfield | STCin | STCforeach | STCparameter | STCresult))
|
||||
|| (storage_class & STCout)) &&
|
||||
@@ -1423,7 +1458,6 @@ Lnomatch:
|
||||
init = new ExpInitializer(e->loc, e);
|
||||
}
|
||||
|
||||
StructInitializer *si = init->isStructInitializer();
|
||||
ExpInitializer *ei = init->isExpInitializer();
|
||||
|
||||
if (ei && isScope())
|
||||
@@ -1492,7 +1526,7 @@ Lnomatch:
|
||||
if (t->ty != Tsarray)
|
||||
break;
|
||||
dim *= ((TypeSArray *)t)->dim->toInteger();
|
||||
e1->type = new TypeSArray(t->nextOf(), new IntegerExp(Loc(), dim, Type::tindex));
|
||||
e1->type = TypeSArray::makeType(Loc(), t->nextOf(), dim);
|
||||
}
|
||||
}
|
||||
e1 = new SliceExp(loc, e1, NULL, NULL);
|
||||
@@ -1641,20 +1675,21 @@ Lnomatch:
|
||||
* Ignore failure.
|
||||
*/
|
||||
|
||||
if (!global.errors && !inferred)
|
||||
if (!inferred)
|
||||
{
|
||||
unsigned errors = global.errors;
|
||||
inuse++;
|
||||
#if DMDV2
|
||||
if (ei)
|
||||
{
|
||||
Expression *exp;
|
||||
exp = ei->exp->syntaxCopy();
|
||||
if (isDataseg() || (storage_class & STCmanifest))
|
||||
exp = exp->ctfeSemantic(sc);
|
||||
else
|
||||
exp = exp->semantic(sc);
|
||||
Expression *exp = ei->exp->syntaxCopy();
|
||||
|
||||
bool needctfe = isDataseg() || (storage_class & STCmanifest);
|
||||
if (needctfe) sc = sc->startCTFE();
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
if (needctfe) sc = sc->endCTFE();
|
||||
|
||||
Type *tb = type->toBasetype();
|
||||
Type *ti = exp->type->toBasetype();
|
||||
|
||||
@@ -1670,30 +1705,17 @@ Lnomatch:
|
||||
* because the postblit doesn't get run on the initialization of w.
|
||||
*/
|
||||
if (ti->ty == Tstruct)
|
||||
{ StructDeclaration *sd = ((TypeStruct *)ti)->sym;
|
||||
{
|
||||
StructDeclaration *sd = ((TypeStruct *)ti)->sym;
|
||||
/* Look to see if initializer involves a copy constructor
|
||||
* (which implies a postblit)
|
||||
*/
|
||||
if (sd->cpctor && // there is a copy constructor
|
||||
tb->equals(ti)) // rvalue is the same struct
|
||||
tb->toDsymbol(NULL) == sd) // exp is the same struct
|
||||
{
|
||||
// The only allowable initializer is a (non-copy) constructor
|
||||
if (exp->op == TOKcall)
|
||||
{
|
||||
CallExp *ce = (CallExp *)exp;
|
||||
if (ce->e1->op == TOKdotvar)
|
||||
{
|
||||
DotVarExp *dve = (DotVarExp *)ce->e1;
|
||||
if (dve->var->isCtorDeclaration())
|
||||
goto LNoCopyConstruction;
|
||||
}
|
||||
}
|
||||
global.gag--;
|
||||
error("of type struct %s uses this(this), which is not allowed in static initialization", tb->toChars());
|
||||
global.gag++;
|
||||
|
||||
LNoCopyConstruction:
|
||||
;
|
||||
if (exp->isLvalue())
|
||||
error("of type struct %s uses this(this), which is not allowed in static initialization", tb->toChars());
|
||||
}
|
||||
}
|
||||
ei->exp = exp;
|
||||
@@ -1722,7 +1744,10 @@ Ldtor:
|
||||
edtor = callScopeDtor(sc);
|
||||
if (edtor)
|
||||
{
|
||||
edtor = edtor->semantic(sc);
|
||||
if (sc->func && storage_class & (STCstatic | STCgshared))
|
||||
edtor = edtor->semantic(sc->module->scope);
|
||||
else
|
||||
edtor = edtor->semantic(sc);
|
||||
|
||||
#if 0 // currently disabled because of std.stdio.stdin, stdout and stderr
|
||||
if (isDataseg() && !(storage_class & STCextern))
|
||||
@@ -1838,7 +1863,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
|
||||
TupleDeclaration *v2 = aliassym->isTupleDeclaration();
|
||||
assert(v2);
|
||||
for (size_t i = 0; i < v2->objects->dim; i++)
|
||||
{ Object *o = (*v2->objects)[i];
|
||||
{ RootObject *o = (*v2->objects)[i];
|
||||
assert(o->dyncast() == DYNCAST_EXPRESSION);
|
||||
Expression *e = (Expression *)o;
|
||||
assert(e->op == TOKdsymbol);
|
||||
@@ -1871,11 +1896,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
|
||||
}
|
||||
if (t->ty == Tstruct || t->ty == Tsarray)
|
||||
{
|
||||
Type *tv = t;
|
||||
while (tv->ty == Tsarray)
|
||||
{
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
Type *tv = t->baseElemOf();
|
||||
if (tv->ty == Tstruct)
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
@@ -1985,23 +2006,23 @@ AggregateDeclaration *VarDeclaration::isThis()
|
||||
return ad;
|
||||
}
|
||||
|
||||
int VarDeclaration::needThis()
|
||||
bool VarDeclaration::needThis()
|
||||
{
|
||||
//printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
|
||||
return isField();
|
||||
}
|
||||
|
||||
int VarDeclaration::isExport()
|
||||
bool VarDeclaration::isExport()
|
||||
{
|
||||
return protection == PROTexport;
|
||||
}
|
||||
|
||||
int VarDeclaration::isImportedSymbol()
|
||||
bool VarDeclaration::isImportedSymbol()
|
||||
{
|
||||
if (protection == PROTexport && !init &&
|
||||
(storage_class & STCstatic || parent->isModule()))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void VarDeclaration::checkCtorConstInit()
|
||||
@@ -2066,7 +2087,7 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
|
||||
* See: compilable/testInference.d
|
||||
*/
|
||||
if (type->isMutable() || // mutable variable
|
||||
!type->implicitConvTo(type->invariantOf()) || // has any mutable indirections
|
||||
!type->implicitConvTo(type->immutableOf()) || // has any mutable indirections
|
||||
!fdv->isPureBypassingInference()) // does not belong to pure function
|
||||
{
|
||||
fld->setImpure(); // Bugzilla 9415
|
||||
@@ -2138,7 +2159,7 @@ Expression *VarDeclaration::getConstInitializer(bool needFullType)
|
||||
if (scope)
|
||||
{
|
||||
inuse++;
|
||||
init->semantic(scope, type, INITinterpret);
|
||||
init = init->semantic(scope, type, INITinterpret);
|
||||
scope = NULL;
|
||||
inuse--;
|
||||
}
|
||||
@@ -2149,10 +2170,10 @@ Expression *VarDeclaration::getConstInitializer(bool needFullType)
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* Return !=0 if we can take the address of this variable.
|
||||
* Return true if we can take the address of this variable.
|
||||
*/
|
||||
|
||||
int VarDeclaration::canTakeAddressOf()
|
||||
bool VarDeclaration::canTakeAddressOf()
|
||||
{
|
||||
#if 0
|
||||
/* Global variables and struct/class fields of the form:
|
||||
@@ -2166,13 +2187,13 @@ int VarDeclaration::canTakeAddressOf()
|
||||
type->toBasetype()->isTypeBasic()
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (storage_class & STCmanifest)
|
||||
return 0;
|
||||
return false;
|
||||
#endif
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2181,7 +2202,7 @@ int VarDeclaration::canTakeAddressOf()
|
||||
* Includes extern variables.
|
||||
*/
|
||||
|
||||
int VarDeclaration::isDataseg()
|
||||
bool VarDeclaration::isDataseg()
|
||||
{
|
||||
#if 0
|
||||
printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
|
||||
@@ -2189,12 +2210,12 @@ int VarDeclaration::isDataseg()
|
||||
printf("parent = '%s'\n", parent->toChars());
|
||||
#endif
|
||||
if (storage_class & STCmanifest)
|
||||
return 0;
|
||||
return false;
|
||||
Dsymbol *parent = this->toParent();
|
||||
if (!parent && !(storage_class & STCstatic))
|
||||
{ error("forward referenced");
|
||||
type = Type::terror;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
return canTakeAddressOf() &&
|
||||
(storage_class & (STCstatic | STCextern | STCtls | STCgshared) ||
|
||||
@@ -2206,7 +2227,7 @@ int VarDeclaration::isDataseg()
|
||||
* Does symbol go into thread local storage?
|
||||
*/
|
||||
|
||||
int VarDeclaration::isThreadlocal()
|
||||
bool VarDeclaration::isThreadlocal()
|
||||
{
|
||||
//printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
|
||||
#if 0 //|| TARGET_OSX
|
||||
@@ -2219,7 +2240,7 @@ int VarDeclaration::isThreadlocal()
|
||||
/* Data defaults to being thread-local. It is not thread-local
|
||||
* if it is immutable, const or shared.
|
||||
*/
|
||||
int i = isDataseg() &&
|
||||
bool i = isDataseg() &&
|
||||
!(storage_class & (STCimmutable | STCconst | STCshared | STCgshared));
|
||||
//printf("\treturn %d\n", i);
|
||||
return i;
|
||||
@@ -2230,29 +2251,29 @@ int VarDeclaration::isThreadlocal()
|
||||
* Can variable be read and written by CTFE?
|
||||
*/
|
||||
|
||||
int VarDeclaration::isCTFE()
|
||||
bool VarDeclaration::isCTFE()
|
||||
{
|
||||
return (storage_class & STCctfe) != 0; // || !isDataseg();
|
||||
}
|
||||
|
||||
int VarDeclaration::hasPointers()
|
||||
bool VarDeclaration::hasPointers()
|
||||
{
|
||||
//printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty);
|
||||
return (!isDataseg() && type->hasPointers());
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Return TRUE if variable needs to call the destructor.
|
||||
* Return true if variable needs to call the destructor.
|
||||
*/
|
||||
|
||||
int VarDeclaration::needsAutoDtor()
|
||||
bool VarDeclaration::needsAutoDtor()
|
||||
{
|
||||
//printf("VarDeclaration::needsAutoDtor() %s\n", toChars());
|
||||
|
||||
if (noscope || !edtor)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2273,19 +2294,14 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc)
|
||||
}
|
||||
|
||||
// Destructors for structs and arrays of structs
|
||||
bool array = false;
|
||||
Type *tv = type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
array = true;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
Type *tv = type->baseElemOf();
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (sd->dtor)
|
||||
{
|
||||
if (array)
|
||||
if (type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
// Typeinfo.destroy(cast(void*)&v);
|
||||
Expression *ea = new SymOffExp(loc, this, 0, 0);
|
||||
@@ -2350,7 +2366,7 @@ void ObjectNotFound(Identifier *id)
|
||||
fatal();
|
||||
}
|
||||
|
||||
/********************************* ClassInfoDeclaration ****************************/
|
||||
/******************************** SymbolDeclaration ********************************/
|
||||
|
||||
SymbolDeclaration::SymbolDeclaration(Loc loc, StructDeclaration *dsym)
|
||||
: Declaration(dsym->ident)
|
||||
@@ -2363,7 +2379,7 @@ SymbolDeclaration::SymbolDeclaration(Loc loc, StructDeclaration *dsym)
|
||||
/********************************* ClassInfoDeclaration ****************************/
|
||||
|
||||
ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd)
|
||||
: VarDeclaration(Loc(), ClassDeclaration::classinfo->type, cd->ident, NULL)
|
||||
: VarDeclaration(Loc(), Type::typeinfoclass->type, cd->ident, NULL)
|
||||
{
|
||||
this->cd = cd;
|
||||
storage_class = STCstatic | STCgshared;
|
||||
@@ -2379,29 +2395,10 @@ void ClassInfoDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
}
|
||||
|
||||
/********************************* ModuleInfoDeclaration ****************************/
|
||||
|
||||
ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod)
|
||||
: VarDeclaration(Loc(), Module::moduleinfo->type, mod->ident, NULL)
|
||||
{
|
||||
this->mod = mod;
|
||||
storage_class = STCstatic | STCgshared;
|
||||
}
|
||||
|
||||
Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s)
|
||||
{
|
||||
assert(0); // should never be produced by syntax
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ModuleInfoDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
}
|
||||
|
||||
/********************************* TypeInfoDeclaration ****************************/
|
||||
|
||||
TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal)
|
||||
: VarDeclaration(Loc(), Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
|
||||
: VarDeclaration(Loc(), Type::dtypeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
|
||||
{
|
||||
this->tinfo = tinfo;
|
||||
storage_class = STCstatic | STCgshared;
|
||||
@@ -2424,6 +2421,17 @@ void TypeInfoDeclaration::semantic(Scope *sc)
|
||||
#endif
|
||||
}
|
||||
|
||||
char *TypeInfoDeclaration::toChars()
|
||||
{
|
||||
//printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo->toChars());
|
||||
OutBuffer buf;
|
||||
buf.writestring("typeid(");
|
||||
buf.writestring(tinfo->toChars());
|
||||
buf.writeByte(')');
|
||||
buf.writeByte(0);
|
||||
return buf.extractData();
|
||||
}
|
||||
|
||||
/***************************** TypeInfoConstDeclaration **********************/
|
||||
|
||||
#if DMDV2
|
||||
|
||||
+210
-185
@@ -30,24 +30,22 @@
|
||||
#include "lexer.h"
|
||||
#include "mtype.h"
|
||||
|
||||
struct Expression;
|
||||
struct Statement;
|
||||
struct LabelDsymbol;
|
||||
#if IN_LLVM
|
||||
struct LabelStatement;
|
||||
#endif
|
||||
struct Initializer;
|
||||
struct Module;
|
||||
class Expression;
|
||||
class Statement;
|
||||
class LabelDsymbol;
|
||||
class Initializer;
|
||||
class Module;
|
||||
struct InlineScanState;
|
||||
struct ForeachStatement;
|
||||
struct FuncDeclaration;
|
||||
struct ExpInitializer;
|
||||
struct StructDeclaration;
|
||||
struct TupleType;
|
||||
class ForeachStatement;
|
||||
class FuncDeclaration;
|
||||
class ExpInitializer;
|
||||
class StructDeclaration;
|
||||
struct InterState;
|
||||
struct IRState;
|
||||
struct CompiledCtfeFunction;
|
||||
#if IN_LLVM
|
||||
struct AnonDeclaration;
|
||||
class AnonDeclaration;
|
||||
class LabelStatement;
|
||||
#endif
|
||||
|
||||
enum PROT;
|
||||
@@ -104,11 +102,11 @@ enum PURE;
|
||||
#define STCtemp 0x10000000000LL // temporary variable introduced by inlining
|
||||
// and used only in backend process, so it's rvalue
|
||||
|
||||
#define STCStorageClass (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal | \
|
||||
STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias | \
|
||||
STCout | STCin | \
|
||||
STCmanifest | STCimmutable | STCshared | STCnothrow | STCpure | STCref | STCtls | \
|
||||
STCgshared | STCproperty | STCsafe | STCtrusted | STCsystem | STCdisable)
|
||||
const StorageClass STCStorageClass = (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal |
|
||||
STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias |
|
||||
STCout | STCin |
|
||||
STCmanifest | STCimmutable | STCshared | STCnothrow | STCpure | STCref | STCtls |
|
||||
STCgshared | STCproperty | STCsafe | STCtrusted | STCsystem | STCdisable);
|
||||
|
||||
struct Match
|
||||
{
|
||||
@@ -119,11 +117,8 @@ struct Match
|
||||
FuncDeclaration *anyf; // pick a func, any func, to use for error recovery
|
||||
};
|
||||
|
||||
void overloadResolveX(Match *m, FuncDeclaration *f,
|
||||
Type *tthis, Expressions *arguments);
|
||||
int overloadApply(FuncDeclaration *fstart,
|
||||
int (*fp)(void *, FuncDeclaration *),
|
||||
void *param);
|
||||
void functionResolve(Match *m, Dsymbol *fd, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs);
|
||||
int overloadApply(Dsymbol *fstart, void *param, int (*fp)(void *, Dsymbol *));
|
||||
|
||||
void ObjectNotFound(Identifier *id);
|
||||
|
||||
@@ -137,16 +132,17 @@ enum Semantic
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct Declaration : Dsymbol
|
||||
class Declaration : public Dsymbol
|
||||
{
|
||||
public:
|
||||
Type *type;
|
||||
Type *originalType; // before semantic analysis
|
||||
StorageClass storage_class;
|
||||
enum PROT protection;
|
||||
enum LINK linkage;
|
||||
PROT protection;
|
||||
LINK linkage;
|
||||
int inuse; // used to detect cycles
|
||||
const char *mangleOverride; // overridden symbol with pragma(mangle, "...")
|
||||
enum Semantic sem;
|
||||
Semantic sem;
|
||||
|
||||
Declaration(Identifier *id);
|
||||
void semantic(Scope *sc);
|
||||
@@ -163,10 +159,10 @@ struct Declaration : Dsymbol
|
||||
|
||||
const char *mangle(bool isv = false);
|
||||
bool isStatic() { return (storage_class & STCstatic) != 0; }
|
||||
virtual int isDelete();
|
||||
virtual int isDataseg();
|
||||
virtual int isThreadlocal();
|
||||
virtual int isCodeseg();
|
||||
virtual bool isDelete();
|
||||
virtual bool isDataseg();
|
||||
virtual bool isThreadlocal();
|
||||
virtual bool isCodeseg();
|
||||
bool isCtorinit() { return (storage_class & STCctorinit) != 0; }
|
||||
bool isFinal() { return (storage_class & STCfinal) != 0; }
|
||||
bool isAbstract() { return (storage_class & STCabstract) != 0; }
|
||||
@@ -186,17 +182,18 @@ struct Declaration : Dsymbol
|
||||
bool isOut() { return (storage_class & STCout) != 0; }
|
||||
bool isRef() { return (storage_class & STCref) != 0; }
|
||||
|
||||
enum PROT prot();
|
||||
PROT prot();
|
||||
|
||||
Declaration *isDeclaration() { return this; }
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct TupleDeclaration : Declaration
|
||||
class TupleDeclaration : public Declaration
|
||||
{
|
||||
public:
|
||||
Objects *objects;
|
||||
int isexp; // 1: expression tuple
|
||||
bool isexp; // true: expression tuple
|
||||
|
||||
TypeTuple *tupletype; // !=NULL if this is a type tuple
|
||||
|
||||
@@ -204,7 +201,7 @@ struct TupleDeclaration : Declaration
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
const char *kind();
|
||||
Type *getType();
|
||||
int needThis();
|
||||
bool needThis();
|
||||
|
||||
TupleDeclaration *isTupleDeclaration() { return this; }
|
||||
|
||||
@@ -217,8 +214,9 @@ struct TupleDeclaration : Declaration
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct TypedefDeclaration : Declaration
|
||||
class TypedefDeclaration : public Declaration
|
||||
{
|
||||
public:
|
||||
Type *basetype;
|
||||
Initializer *init;
|
||||
|
||||
@@ -257,18 +255,19 @@ struct TypedefDeclaration : Declaration
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct AliasDeclaration : Declaration
|
||||
class AliasDeclaration : public Declaration
|
||||
{
|
||||
public:
|
||||
Dsymbol *aliassym;
|
||||
Dsymbol *overnext; // next in overload list
|
||||
Dsymbol *import; // !=NULL if unresolved internal alias for selective import
|
||||
int inSemantic;
|
||||
bool inSemantic;
|
||||
|
||||
AliasDeclaration(Loc loc, Identifier *ident, Type *type);
|
||||
AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
bool overloadInsert(Dsymbol *s);
|
||||
const char *kind();
|
||||
Type *getType();
|
||||
Dsymbol *toAlias();
|
||||
@@ -283,8 +282,9 @@ struct AliasDeclaration : Declaration
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct VarDeclaration : Declaration
|
||||
class VarDeclaration : public Declaration
|
||||
{
|
||||
public:
|
||||
Initializer *init;
|
||||
unsigned offset;
|
||||
bool noscope; // no auto semantics
|
||||
@@ -329,16 +329,16 @@ struct VarDeclaration : Declaration
|
||||
Type *htype;
|
||||
Initializer *hinit;
|
||||
AggregateDeclaration *isThis();
|
||||
int needThis();
|
||||
int isExport();
|
||||
int isImportedSymbol();
|
||||
int isDataseg();
|
||||
int isThreadlocal();
|
||||
int isCTFE();
|
||||
int hasPointers();
|
||||
bool needThis();
|
||||
bool isExport();
|
||||
bool isImportedSymbol();
|
||||
bool isDataseg();
|
||||
bool isThreadlocal();
|
||||
bool isCTFE();
|
||||
bool hasPointers();
|
||||
#if DMDV2
|
||||
int canTakeAddressOf();
|
||||
int needsAutoDtor();
|
||||
bool canTakeAddressOf();
|
||||
bool needsAutoDtor();
|
||||
#endif
|
||||
Expression *callScopeDtor(Scope *sc);
|
||||
ExpInitializer *getExpInitializer();
|
||||
@@ -347,8 +347,8 @@ struct VarDeclaration : Declaration
|
||||
void checkNestedReference(Scope *sc, Loc loc);
|
||||
Dsymbol *toAlias();
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
Symbol *toSymbol();
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
int cvMember(unsigned char *p);
|
||||
#endif
|
||||
const char *mangle(bool isv = false);
|
||||
@@ -381,8 +381,9 @@ struct VarDeclaration : Declaration
|
||||
|
||||
// This is a shell around a back end symbol
|
||||
|
||||
struct SymbolDeclaration : Declaration
|
||||
class SymbolDeclaration : public Declaration
|
||||
{
|
||||
public:
|
||||
StructDeclaration *dsym;
|
||||
|
||||
SymbolDeclaration(Loc loc, StructDeclaration *dsym);
|
||||
@@ -395,8 +396,9 @@ struct SymbolDeclaration : Declaration
|
||||
SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; }
|
||||
};
|
||||
|
||||
struct ClassInfoDeclaration : VarDeclaration
|
||||
class ClassInfoDeclaration : public VarDeclaration
|
||||
{
|
||||
public:
|
||||
ClassDeclaration *cd;
|
||||
|
||||
ClassInfoDeclaration(ClassDeclaration *cd);
|
||||
@@ -413,40 +415,25 @@ struct ClassInfoDeclaration : VarDeclaration
|
||||
ClassInfoDeclaration* isClassInfoDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct ModuleInfoDeclaration : VarDeclaration
|
||||
{
|
||||
Module *mod;
|
||||
|
||||
ModuleInfoDeclaration(Module *mod);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toJson(JsonOut *json);
|
||||
|
||||
#if IN_DMD
|
||||
Symbol *toSymbol();
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoDeclaration : VarDeclaration
|
||||
class TypeInfoDeclaration : public VarDeclaration
|
||||
{
|
||||
public:
|
||||
Type *tinfo;
|
||||
|
||||
TypeInfoDeclaration(Type *tinfo, int internal);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
char *toChars();
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toJson(JsonOut *json);
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
Symbol *toSymbol();
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
virtual void toDt(dt_t **pdt);
|
||||
#endif
|
||||
|
||||
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return this; }
|
||||
TypeInfoDeclaration *isTypeInfoDeclaration() { return this; }
|
||||
|
||||
#if IN_LLVM
|
||||
/// Codegen traversal
|
||||
@@ -455,8 +442,9 @@ struct TypeInfoDeclaration : VarDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoStructDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoStructDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoStructDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -468,8 +456,9 @@ struct TypeInfoStructDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoClassDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoClassDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoClassDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -487,8 +476,9 @@ struct TypeInfoClassDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoInterfaceDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoInterfaceDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -500,8 +490,9 @@ struct TypeInfoInterfaceDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoTypedefDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoTypedefDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -513,8 +504,9 @@ struct TypeInfoTypedefDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoPointerDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoPointerDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoPointerDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -526,8 +518,9 @@ struct TypeInfoPointerDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoArrayDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoArrayDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoArrayDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -539,8 +532,9 @@ struct TypeInfoArrayDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoStaticArrayDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoStaticArrayDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -552,8 +546,9 @@ struct TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoAssociativeArrayDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoAssociativeArrayDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -565,8 +560,9 @@ struct TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoEnumDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoEnumDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoEnumDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -578,8 +574,9 @@ struct TypeInfoEnumDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoFunctionDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoFunctionDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -591,8 +588,9 @@ struct TypeInfoFunctionDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoDelegateDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoDelegateDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -604,8 +602,9 @@ struct TypeInfoDelegateDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoTupleDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoTupleDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoTupleDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -618,8 +617,9 @@ struct TypeInfoTupleDeclaration : TypeInfoDeclaration
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct TypeInfoConstDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoConstDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoConstDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -631,8 +631,9 @@ struct TypeInfoConstDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoInvariantDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoInvariantDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoInvariantDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -644,8 +645,9 @@ struct TypeInfoInvariantDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoSharedDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoSharedDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoSharedDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -657,8 +659,9 @@ struct TypeInfoSharedDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoWildDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoWildDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoWildDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -670,8 +673,9 @@ struct TypeInfoWildDeclaration : TypeInfoDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeInfoVectorDeclaration : TypeInfoDeclaration
|
||||
class TypeInfoVectorDeclaration : public TypeInfoDeclaration
|
||||
{
|
||||
public:
|
||||
TypeInfoVectorDeclaration(Type *tinfo);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -686,8 +690,9 @@ struct TypeInfoVectorDeclaration : TypeInfoDeclaration
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
struct ThisDeclaration : VarDeclaration
|
||||
class ThisDeclaration : public VarDeclaration
|
||||
{
|
||||
public:
|
||||
ThisDeclaration(Loc loc, Type *t);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
ThisDeclaration *isThisDeclaration() { return this; }
|
||||
@@ -726,14 +731,15 @@ enum BUILTIN
|
||||
#endif
|
||||
};
|
||||
|
||||
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments);
|
||||
Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments);
|
||||
|
||||
#else
|
||||
enum BUILTIN { };
|
||||
#endif
|
||||
|
||||
struct FuncDeclaration : Declaration
|
||||
class FuncDeclaration : public Declaration
|
||||
{
|
||||
public:
|
||||
Types *fthrows; // Array of Type's of exceptions (not used)
|
||||
Statement *frequire;
|
||||
Statement *fensure;
|
||||
@@ -766,28 +772,30 @@ struct FuncDeclaration : Declaration
|
||||
VarDeclaration *v_argsave; // save area for args passed in registers for variadic functions
|
||||
VarDeclarations *parameters; // Array of VarDeclaration's for parameters
|
||||
DsymbolTable *labtab; // statement label symbol table
|
||||
Declaration *overnext; // next in overload list
|
||||
Dsymbol *overnext; // next in overload list
|
||||
FuncDeclaration *overnext0; // next in overload list (only used during IFTI)
|
||||
Loc endloc; // location of closing curly bracket
|
||||
int vtblIndex; // for member functions, index into vtbl[]
|
||||
bool naked; // !=0 if naked
|
||||
bool naked; // true if naked
|
||||
ILS inlineStatusStmt;
|
||||
ILS inlineStatusExp;
|
||||
|
||||
CompiledCtfeFunction *ctfeCode; // Compiled code for interpreter
|
||||
int inlineNest; // !=0 if nested inline
|
||||
#if IN_LLVM
|
||||
char isArrayOp; // 1 if compiler-generated array op, 2 if druntime-provided
|
||||
#else
|
||||
bool isArrayOp; // !=0 if array operation
|
||||
bool isArrayOp; // true if array operation
|
||||
#endif
|
||||
FuncDeclaration *dArrayOp; // D version of array op for ctfe
|
||||
enum PASS semanticRun;
|
||||
int semantic3Errors; // !=0 if errors in semantic3
|
||||
// this function's frame ptr
|
||||
ForeachStatement *fes; // if foreach body, this is the foreach
|
||||
bool introducing; // !=0 if 'introducing' function
|
||||
bool introducing; // true if 'introducing' function
|
||||
Type *tintro; // if !=NULL, then this is the type
|
||||
// of the 'introducing' function
|
||||
// this one is overriding
|
||||
int inferRetType; // !=0 if return type is to be inferred
|
||||
bool inferRetType; // true if return type is to be inferred
|
||||
StorageClass storage_class2; // storage class for template onemember's
|
||||
|
||||
// Things that should really go into Scope
|
||||
@@ -797,7 +805,7 @@ struct FuncDeclaration : Declaration
|
||||
// 8 if there's inline asm
|
||||
|
||||
// Support for NRVO (named return value optimization)
|
||||
bool nrvo_can; // !=0 means we can do it
|
||||
bool nrvo_can; // true means we can do it
|
||||
VarDeclaration *nrvo_var; // variable to replace with shidden
|
||||
#if IN_DMD
|
||||
Symbol *shidden; // hidden pointer passed to function
|
||||
@@ -806,7 +814,7 @@ struct FuncDeclaration : Declaration
|
||||
ReturnStatements *returns;
|
||||
|
||||
#if DMDV2
|
||||
enum BUILTIN builtin; // set if this is a known, builtin
|
||||
BUILTIN builtin; // set if this is a known, builtin
|
||||
// function we can evaluate at compile
|
||||
// time
|
||||
|
||||
@@ -839,16 +847,16 @@ struct FuncDeclaration : Declaration
|
||||
bool functionSemantic3();
|
||||
// called from semantic3
|
||||
VarDeclaration *declareThis(Scope *sc, AggregateDeclaration *ad);
|
||||
int equals(Object *o);
|
||||
bool equals(RootObject *o);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void toJson(JsonOut *json);
|
||||
int overrides(FuncDeclaration *fd);
|
||||
int findVtblIndex(Dsymbols *vtbl, int dim);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
bool overloadInsert(Dsymbol *s);
|
||||
FuncDeclaration *overloadExactMatch(Type *t);
|
||||
FuncDeclaration *overloadResolve(Loc loc, Type *tthis, Expressions *arguments, int flags = 0);
|
||||
TemplateDeclaration *findTemplateDeclRoot();
|
||||
MATCH leastAsSpecialized(FuncDeclaration *g);
|
||||
LabelDsymbol *searchLabel(Identifier *ident);
|
||||
AggregateDeclaration *isThis();
|
||||
@@ -857,35 +865,36 @@ struct FuncDeclaration : Declaration
|
||||
void appendExp(Expression *e);
|
||||
void appendState(Statement *s);
|
||||
const char *mangle(bool isv = false);
|
||||
const char *mangleExact(bool isv = false);
|
||||
const char *toPrettyChars();
|
||||
const char *toFullSignature(); // for diagnostics, e.g. 'int foo(int x, int y) pure'
|
||||
int isMain();
|
||||
int isWinMain();
|
||||
int isDllMain();
|
||||
enum BUILTIN isBuiltin();
|
||||
int isExport();
|
||||
int isImportedSymbol();
|
||||
int isAbstract();
|
||||
int isCodeseg();
|
||||
int isOverloadable();
|
||||
int hasOverloads();
|
||||
enum PURE isPure();
|
||||
enum PURE isPureBypassingInference();
|
||||
bool isMain();
|
||||
bool isWinMain();
|
||||
bool isDllMain();
|
||||
BUILTIN isBuiltin();
|
||||
bool isExport();
|
||||
bool isImportedSymbol();
|
||||
bool isCodeseg();
|
||||
bool isOverloadable();
|
||||
bool hasOverloads();
|
||||
PURE isPure();
|
||||
PURE isPureBypassingInference();
|
||||
bool setImpure();
|
||||
int isSafe();
|
||||
bool isSafe();
|
||||
bool isSafeBypassingInference();
|
||||
int isTrusted();
|
||||
bool isTrusted();
|
||||
bool setUnsafe();
|
||||
bool isolateReturn();
|
||||
bool parametersIntersect(Type *t);
|
||||
virtual int isNested();
|
||||
int needThis();
|
||||
int isVirtualMethod();
|
||||
virtual int isVirtual();
|
||||
virtual int isFinal();
|
||||
virtual int addPreInvariant();
|
||||
virtual int addPostInvariant();
|
||||
virtual bool isNested();
|
||||
bool needThis();
|
||||
bool isVirtualMethod();
|
||||
virtual bool isVirtual();
|
||||
virtual bool isFinalFunc();
|
||||
virtual bool addPreInvariant();
|
||||
virtual bool addPostInvariant();
|
||||
Expression *interpret(InterState *istate, Expressions *arguments, Expression *thisexp = NULL);
|
||||
void ctfeCompile();
|
||||
void inlineScan();
|
||||
int canInline(int hasthis, int hdrscan, int statementsToo);
|
||||
Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps);
|
||||
@@ -893,11 +902,11 @@ struct FuncDeclaration : Declaration
|
||||
void toDocBuffer(OutBuffer *buf, Scope *sc);
|
||||
FuncDeclaration *isUnique();
|
||||
void checkNestedReference(Scope *sc, Loc loc);
|
||||
int needsClosure();
|
||||
int hasNestedFrameRefs();
|
||||
bool needsClosure();
|
||||
bool hasNestedFrameRefs();
|
||||
void buildResultVar();
|
||||
Statement *mergeFrequire(Statement *, Expressions *params = 0);
|
||||
Statement *mergeFensure(Statement *, Expressions *params = 0);
|
||||
Statement *mergeFensure(Statement *, Identifier *oid, Expressions *params = 0);
|
||||
Parameters *getParameters(int *pvarargs);
|
||||
|
||||
// LDC: give argument types to runtime functions
|
||||
@@ -959,34 +968,36 @@ FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
|
||||
int flags = 0);
|
||||
#endif
|
||||
|
||||
struct FuncAliasDeclaration : FuncDeclaration
|
||||
class FuncAliasDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
FuncDeclaration *funcalias;
|
||||
int hasOverloads;
|
||||
bool hasOverloads;
|
||||
|
||||
FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads = 1);
|
||||
FuncAliasDeclaration(FuncDeclaration *funcalias, bool hasOverloads = true);
|
||||
|
||||
FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
|
||||
const char *kind();
|
||||
#if IN_DMD
|
||||
Symbol *toSymbol();
|
||||
#endif
|
||||
const char *mangle(bool isv = false) { return toAliasFunc()->mangle(isv); }
|
||||
const char *mangle(bool isv = false);
|
||||
|
||||
FuncDeclaration *toAliasFunc();
|
||||
};
|
||||
|
||||
struct FuncLiteralDeclaration : FuncDeclaration
|
||||
class FuncLiteralDeclaration : public FuncDeclaration
|
||||
{
|
||||
enum TOK tok; // TOKfunction or TOKdelegate
|
||||
public:
|
||||
TOK tok; // TOKfunction or TOKdelegate
|
||||
Type *treq; // target of return type inference
|
||||
|
||||
FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok,
|
||||
ForeachStatement *fes);
|
||||
FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, TOK tok,
|
||||
ForeachStatement *fes, Identifier *id = NULL);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
int isNested();
|
||||
int isVirtual();
|
||||
bool isNested();
|
||||
bool isVirtual();
|
||||
|
||||
FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; }
|
||||
const char *kind();
|
||||
@@ -1002,40 +1013,43 @@ struct FuncLiteralDeclaration : FuncDeclaration
|
||||
#endif
|
||||
};
|
||||
|
||||
struct CtorDeclaration : FuncDeclaration
|
||||
class CtorDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
const char *kind();
|
||||
char *toChars();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
|
||||
CtorDeclaration *isCtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct PostBlitDeclaration : FuncDeclaration
|
||||
class PostBlitDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void toJson(JsonOut *json);
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
int overloadInsert(Dsymbol *s);
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
bool overloadInsert(Dsymbol *s);
|
||||
void emitComment(Scope *sc);
|
||||
|
||||
PostBlitDeclaration *isPostBlitDeclaration() { return this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
struct DtorDeclaration : FuncDeclaration
|
||||
class DtorDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
DtorDeclaration(Loc loc, Loc endloc);
|
||||
DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
@@ -1043,25 +1057,26 @@ struct DtorDeclaration : FuncDeclaration
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
char *toChars();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
int overloadInsert(Dsymbol *s);
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
bool overloadInsert(Dsymbol *s);
|
||||
void emitComment(Scope *sc);
|
||||
|
||||
DtorDeclaration *isDtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct StaticCtorDeclaration : FuncDeclaration
|
||||
class StaticCtorDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
StaticCtorDeclaration(Loc loc, Loc endloc);
|
||||
StaticCtorDeclaration(Loc loc, Loc endloc, const char *name);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
AggregateDeclaration *isThis();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
bool hasStaticCtorOrDtor();
|
||||
void emitComment(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -1070,8 +1085,9 @@ struct StaticCtorDeclaration : FuncDeclaration
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct SharedStaticCtorDeclaration : StaticCtorDeclaration
|
||||
class SharedStaticCtorDeclaration : public StaticCtorDeclaration
|
||||
{
|
||||
public:
|
||||
SharedStaticCtorDeclaration(Loc loc, Loc endloc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -1080,18 +1096,20 @@ struct SharedStaticCtorDeclaration : StaticCtorDeclaration
|
||||
};
|
||||
#endif
|
||||
|
||||
struct StaticDtorDeclaration : FuncDeclaration
|
||||
{ VarDeclaration *vgate; // 'gate' variable
|
||||
class StaticDtorDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
VarDeclaration *vgate; // 'gate' variable
|
||||
|
||||
StaticDtorDeclaration(Loc loc, Loc endloc);
|
||||
StaticDtorDeclaration(Loc loc, Loc endloc, const char *name);
|
||||
StaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc);
|
||||
StaticDtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
AggregateDeclaration *isThis();
|
||||
int isVirtual();
|
||||
bool isVirtual();
|
||||
bool hasStaticCtorOrDtor();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
void emitComment(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -1099,9 +1117,10 @@ struct StaticDtorDeclaration : FuncDeclaration
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct SharedStaticDtorDeclaration : StaticDtorDeclaration
|
||||
class SharedStaticDtorDeclaration : public StaticDtorDeclaration
|
||||
{
|
||||
SharedStaticDtorDeclaration(Loc loc, Loc endloc);
|
||||
public:
|
||||
SharedStaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -1109,38 +1128,42 @@ struct SharedStaticDtorDeclaration : StaticDtorDeclaration
|
||||
};
|
||||
#endif
|
||||
|
||||
struct InvariantDeclaration : FuncDeclaration
|
||||
class InvariantDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
InvariantDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id = NULL);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
void emitComment(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
InvariantDeclaration *isInvariantDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct UnitTestDeclaration : FuncDeclaration
|
||||
class UnitTestDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
char *codedoc; /** For documented unittest. */
|
||||
UnitTestDeclaration(Loc loc, Loc endloc, char *codedoc);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
AggregateDeclaration *isThis();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
void emitComment(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
|
||||
};
|
||||
|
||||
struct NewDeclaration : FuncDeclaration
|
||||
{ Parameters *arguments;
|
||||
class NewDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
Parameters *arguments;
|
||||
int varargs;
|
||||
|
||||
NewDeclaration(Loc loc, Loc endloc, Parameters *arguments, int varargs);
|
||||
@@ -1148,26 +1171,28 @@ struct NewDeclaration : FuncDeclaration
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
|
||||
NewDeclaration *isNewDeclaration() { return this; }
|
||||
};
|
||||
|
||||
|
||||
struct DeleteDeclaration : FuncDeclaration
|
||||
{ Parameters *arguments;
|
||||
class DeleteDeclaration : public FuncDeclaration
|
||||
{
|
||||
public:
|
||||
Parameters *arguments;
|
||||
|
||||
DeleteDeclaration(Loc loc, Loc endloc, Parameters *arguments);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
const char *kind();
|
||||
int isDelete();
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
bool isDelete();
|
||||
bool isVirtual();
|
||||
bool addPreInvariant();
|
||||
bool addPostInvariant();
|
||||
DeleteDeclaration *isDeleteDeclaration() { return this; }
|
||||
};
|
||||
|
||||
|
||||
+214
-114
@@ -44,12 +44,13 @@ struct Escape
|
||||
const char *escapeChar(unsigned c);
|
||||
};
|
||||
|
||||
struct Section
|
||||
class Section
|
||||
{
|
||||
unsigned char *name;
|
||||
public:
|
||||
utf8_t *name;
|
||||
size_t namelen;
|
||||
|
||||
unsigned char *body;
|
||||
utf8_t *body;
|
||||
size_t bodylen;
|
||||
|
||||
int nooutput;
|
||||
@@ -57,17 +58,19 @@ struct Section
|
||||
virtual void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
|
||||
};
|
||||
|
||||
struct ParamSection : Section
|
||||
class ParamSection : public Section
|
||||
{
|
||||
public:
|
||||
void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
|
||||
};
|
||||
|
||||
struct MacroSection : Section
|
||||
class MacroSection : public Section
|
||||
{
|
||||
public:
|
||||
void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf);
|
||||
};
|
||||
|
||||
typedef ArrayBase<Section> Sections;
|
||||
typedef Array<Section> Sections;
|
||||
|
||||
struct DocComment
|
||||
{
|
||||
@@ -83,31 +86,33 @@ struct DocComment
|
||||
summary(NULL), copyright(NULL), macros(NULL), pmacrotable(NULL), pescapetable(NULL)
|
||||
{ }
|
||||
|
||||
static DocComment *parse(Scope *sc, Dsymbol *s, unsigned char *comment);
|
||||
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, size_t mlen);
|
||||
static void parseEscapes(Escape **pescapetable, unsigned char *textstart, size_t textlen);
|
||||
static DocComment *parse(Scope *sc, Dsymbol *s, utf8_t *comment);
|
||||
static void parseMacros(Escape **pescapetable, Macro **pmacrotable, utf8_t *m, size_t mlen);
|
||||
static void parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t textlen);
|
||||
|
||||
void parseSections(unsigned char *comment);
|
||||
void parseSections(utf8_t *comment);
|
||||
void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf);
|
||||
};
|
||||
|
||||
|
||||
int cmp(const char *stringz, void *s, size_t slen);
|
||||
int icmp(const char *stringz, void *s, size_t slen);
|
||||
int isDitto(unsigned char *comment);
|
||||
unsigned char *skipwhitespace(unsigned char *p);
|
||||
int isDitto(utf8_t *comment);
|
||||
utf8_t *skipwhitespace(utf8_t *p);
|
||||
size_t skiptoident(OutBuffer *buf, size_t i);
|
||||
size_t skippastident(OutBuffer *buf, size_t i);
|
||||
size_t skippastURL(OutBuffer *buf, size_t i);
|
||||
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
|
||||
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool anchor = true);
|
||||
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset);
|
||||
Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, size_t len);
|
||||
TypeFunction *isTypeFunction(Dsymbol *s);
|
||||
Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len);
|
||||
TemplateParameter *isTemplateParameter(Dsymbol *s, utf8_t *p, size_t len);
|
||||
|
||||
int isIdStart(unsigned char *p);
|
||||
int isIdTail(unsigned char *p);
|
||||
int isIndentWS(unsigned char *p);
|
||||
int utfStride(unsigned char *p);
|
||||
int isIdStart(utf8_t *p);
|
||||
int isIdTail(utf8_t *p);
|
||||
int isIndentWS(utf8_t *p);
|
||||
int utfStride(utf8_t *p);
|
||||
|
||||
static const char ddoc_default[] = "\
|
||||
DDOC = <html><head>\n\
|
||||
@@ -185,6 +190,7 @@ DDOC_CLASS_MEMBERS = $(DDOC_MEMBERS $0)\n\
|
||||
DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0)\n\
|
||||
DDOC_ENUM_MEMBERS = $(DDOC_MEMBERS $0)\n\
|
||||
DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0)\n\
|
||||
DDOC_ENUM_BASETYPE = $0\n\
|
||||
DDOC_PARAMS = $(B Params:)$(BR)\n$(TABLE $0)$(BR)\n\
|
||||
DDOC_PARAM_ROW = $(TR $0)\n\
|
||||
DDOC_PARAM_ID = $(TD $0)\n\
|
||||
@@ -224,7 +230,7 @@ void Module::gendocfile()
|
||||
{ mbuf_done = 1;
|
||||
|
||||
// Use our internal default
|
||||
mbuf.write(ddoc_default, sizeof(ddoc_default) - 1);
|
||||
mbuf.write(ddoc_default, strlen(ddoc_default));
|
||||
|
||||
// Override with DDOCFILE specified in the sc.ini file
|
||||
char *p = getenv("DDOCFILE");
|
||||
@@ -256,7 +262,7 @@ void Module::gendocfile()
|
||||
|
||||
// Set the title to be the name of the module
|
||||
{ const char *p = toPrettyChars();
|
||||
Macro::define(¯otable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p));
|
||||
Macro::define(¯otable, (utf8_t *)"TITLE", 5, (utf8_t *)p, strlen(p));
|
||||
}
|
||||
|
||||
// Set time macros
|
||||
@@ -264,20 +270,20 @@ void Module::gendocfile()
|
||||
time(&t);
|
||||
char *p = ctime(&t);
|
||||
p = mem.strdup(p);
|
||||
Macro::define(¯otable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p));
|
||||
Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
|
||||
Macro::define(¯otable, (utf8_t *)"DATETIME", 8, (utf8_t *)p, strlen(p));
|
||||
Macro::define(¯otable, (utf8_t *)"YEAR", 4, (utf8_t *)p + 20, 4);
|
||||
}
|
||||
|
||||
char *srcfilename = srcfile->toChars();
|
||||
Macro::define(¯otable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename));
|
||||
Macro::define(¯otable, (utf8_t *)"SRCFILENAME", 11, (utf8_t *)srcfilename, strlen(srcfilename));
|
||||
|
||||
char *docfilename = docfile->toChars();
|
||||
Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
|
||||
Macro::define(¯otable, (utf8_t *)"DOCFILENAME", 11, (utf8_t *)docfilename, strlen(docfilename));
|
||||
|
||||
if (dc->copyright)
|
||||
{
|
||||
dc->copyright->nooutput = 1;
|
||||
Macro::define(¯otable, (unsigned char *)"COPYRIGHT", 9, dc->copyright->body, dc->copyright->bodylen);
|
||||
Macro::define(¯otable, (utf8_t *)"COPYRIGHT", 9, dc->copyright->body, dc->copyright->bodylen);
|
||||
}
|
||||
|
||||
buf.printf("$(DDOC_COMMENT Generated by Ddoc from %s)\n", srcfile->toChars());
|
||||
@@ -299,7 +305,7 @@ void Module::gendocfile()
|
||||
}
|
||||
|
||||
//printf("BODY= '%.*s'\n", buf.offset, buf.data);
|
||||
Macro::define(¯otable, (unsigned char *)"BODY", 4, buf.data, buf.offset);
|
||||
Macro::define(¯otable, (utf8_t *)"BODY", 4, buf.data, buf.offset);
|
||||
|
||||
OutBuffer buf2;
|
||||
buf2.writestring("$(DDOC)\n");
|
||||
@@ -313,10 +319,10 @@ void Module::gendocfile()
|
||||
{
|
||||
buf.setsize(0);
|
||||
buf.reserve(buf2.offset);
|
||||
unsigned char *p = buf2.data;
|
||||
utf8_t *p = buf2.data;
|
||||
for (size_t j = 0; j < buf2.offset; j++)
|
||||
{
|
||||
unsigned char c = p[j];
|
||||
utf8_t c = p[j];
|
||||
if (c == 0xFF && j + 1 < buf2.offset)
|
||||
{
|
||||
j++;
|
||||
@@ -347,7 +353,7 @@ void Module::gendocfile()
|
||||
/* Remove all the escape sequences from buf2
|
||||
*/
|
||||
{ size_t i = 0;
|
||||
unsigned char *p = buf2.data;
|
||||
utf8_t *p = buf2.data;
|
||||
for (size_t j = 0; j < buf2.offset; j++)
|
||||
{
|
||||
if (p[j] == 0xFF && j + 1 < buf2.offset)
|
||||
@@ -380,7 +386,7 @@ void escapeDdocString(OutBuffer *buf, size_t start)
|
||||
{
|
||||
for (size_t u = start; u < buf->offset; u++)
|
||||
{
|
||||
unsigned char c = buf->data[u];
|
||||
utf8_t c = buf->data[u];
|
||||
switch(c)
|
||||
{
|
||||
case '$':
|
||||
@@ -410,13 +416,20 @@ void escapeDdocString(OutBuffer *buf, size_t start)
|
||||
|
||||
* Fix by replacing unmatched ( with $(LPAREN) and unmatched ) with $(RPAREN).
|
||||
*/
|
||||
void escapeStrayParenthesis(OutBuffer *buf, size_t start, Loc loc)
|
||||
void escapeStrayParenthesis(OutBuffer *buf, size_t start, Dsymbol *s)
|
||||
{
|
||||
unsigned par_open = 0;
|
||||
Loc loc = s->loc;
|
||||
|
||||
if (Module *m = s->isModule())
|
||||
{
|
||||
if (m->md)
|
||||
loc = m->md->loc;
|
||||
}
|
||||
|
||||
for (size_t u = start; u < buf->offset; u++)
|
||||
{
|
||||
unsigned char c = buf->data[u];
|
||||
utf8_t c = buf->data[u];
|
||||
switch(c)
|
||||
{
|
||||
case '(':
|
||||
@@ -451,7 +464,7 @@ void escapeStrayParenthesis(OutBuffer *buf, size_t start, Loc loc)
|
||||
{ par_open = 0;
|
||||
for (size_t u = buf->offset; u > start;)
|
||||
{ u--;
|
||||
unsigned char c = buf->data[u];
|
||||
utf8_t c = buf->data[u];
|
||||
switch(c)
|
||||
{
|
||||
case ')':
|
||||
@@ -501,6 +514,7 @@ static bool emitAnchorName(OutBuffer *buf, Dsymbol *s)
|
||||
* We don't want the template parameter list and constraints. */
|
||||
buf->writestring(s->Dsymbol::toChars());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -532,13 +546,13 @@ void emitUnittestComment(Scope *sc, Dsymbol *s, size_t ofs)
|
||||
{
|
||||
OutBuffer *buf = sc->docbuf;
|
||||
|
||||
for (UnitTestDeclaration *utd = s->unittest; utd; utd = utd->unittest)
|
||||
for (UnitTestDeclaration *utd = s->ddocUnittest; utd; utd = utd->ddocUnittest)
|
||||
{
|
||||
if (utd->protection == PROTprivate || !utd->comment || !utd->fbody)
|
||||
continue;
|
||||
|
||||
// Strip whitespaces to avoid showing empty summary
|
||||
unsigned char *c = utd->comment;
|
||||
utf8_t *c = utd->comment;
|
||||
while (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r') ++c;
|
||||
|
||||
OutBuffer codebuf;
|
||||
@@ -593,7 +607,7 @@ void Dsymbol::emitDitto(Scope *sc)
|
||||
sc->lastoffset += b.offset;
|
||||
|
||||
Dsymbol *s = this;
|
||||
if (!s->unittest && parent)
|
||||
if (!s->ddocUnittest && parent)
|
||||
s = parent->isTemplateDeclaration();
|
||||
if (s)
|
||||
emitUnittestComment(sc, s, strlen(ddoc_decl_dd_e));
|
||||
@@ -658,7 +672,6 @@ void DtorDeclaration::emitComment(Scope *sc) { }
|
||||
void StaticCtorDeclaration::emitComment(Scope *sc) { }
|
||||
void StaticDtorDeclaration::emitComment(Scope *sc) { }
|
||||
void ClassInfoDeclaration::emitComment(Scope *sc) { }
|
||||
void ModuleInfoDeclaration::emitComment(Scope *sc) { }
|
||||
void TypeInfoDeclaration::emitComment(Scope *sc) { }
|
||||
|
||||
|
||||
@@ -733,7 +746,7 @@ void TemplateDeclaration::emitComment(Scope *sc)
|
||||
if (prot() == PROTprivate)
|
||||
return;
|
||||
|
||||
unsigned char *com = comment;
|
||||
utf8_t *com = comment;
|
||||
int hasmembers = 1;
|
||||
|
||||
Dsymbol *ss = this;
|
||||
@@ -883,14 +896,17 @@ void prefix(OutBuffer *buf, Dsymbol *s)
|
||||
else if (d->isAbstract())
|
||||
buf->writestring("abstract ");
|
||||
|
||||
if (d->isConst())
|
||||
buf->writestring("const ");
|
||||
#if DMDV2
|
||||
if (d->isImmutable())
|
||||
buf->writestring("immutable ");
|
||||
#endif
|
||||
if (d->isSynchronized())
|
||||
buf->writestring("synchronized ");
|
||||
if (!d->isFuncDeclaration()) // toCBufferWithAttributes handles this
|
||||
{
|
||||
if (d->isConst())
|
||||
buf->writestring("const ");
|
||||
#if DMDV2
|
||||
if (d->isImmutable())
|
||||
buf->writestring("immutable ");
|
||||
#endif
|
||||
if (d->isSynchronized())
|
||||
buf->writestring("synchronized ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -919,6 +935,16 @@ void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclarati
|
||||
else
|
||||
buf->writestring(decl->ident->toChars());
|
||||
|
||||
// emit constraints if declaration is a templated declaration
|
||||
if (td && td->constraint)
|
||||
{
|
||||
HdrGenState hgs;
|
||||
hgs.ddoc = 1;
|
||||
buf->writestring(" if (");
|
||||
td->constraint->toCBuffer(buf, &hgs);
|
||||
buf->writeByte(')');
|
||||
}
|
||||
|
||||
if (decl->isDeprecated())
|
||||
buf->writestring(")");
|
||||
|
||||
@@ -1122,7 +1148,7 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isAbstract())
|
||||
if (!isInterfaceDeclaration() && isAbstract())
|
||||
buf->writestring("abstract ");
|
||||
buf->printf("%s %s", kind(), toChars());
|
||||
}
|
||||
@@ -1162,6 +1188,13 @@ void EnumDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
|
||||
if (ident)
|
||||
{
|
||||
buf->printf("%s %s", kind(), toChars());
|
||||
if (memtype)
|
||||
{
|
||||
buf->writestring(": $(DDOC_ENUM_BASETYPE ");
|
||||
HdrGenState *hgs = NULL;
|
||||
memtype->toCBuffer(buf, NULL, hgs);
|
||||
buf->writestring(")");
|
||||
}
|
||||
buf->writestring(";\n");
|
||||
}
|
||||
}
|
||||
@@ -1177,7 +1210,7 @@ void EnumMember::toDocBuffer(OutBuffer *buf, Scope *sc)
|
||||
|
||||
/********************************* DocComment *********************************/
|
||||
|
||||
DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment)
|
||||
DocComment *DocComment::parse(Scope *sc, Dsymbol *s, utf8_t *comment)
|
||||
{
|
||||
//printf("parse(%s): '%s'\n", s->toChars(), comment);
|
||||
if (sc->lastdc && isDitto(comment))
|
||||
@@ -1214,21 +1247,21 @@ DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment)
|
||||
* then (*pcomment)[0 .. idlen] is the identifier.
|
||||
*/
|
||||
|
||||
void DocComment::parseSections(unsigned char *comment)
|
||||
{ unsigned char *p;
|
||||
unsigned char *pstart;
|
||||
unsigned char *pend;
|
||||
unsigned char *idstart;
|
||||
void DocComment::parseSections(utf8_t *comment)
|
||||
{ utf8_t *p;
|
||||
utf8_t *pstart;
|
||||
utf8_t *pend;
|
||||
utf8_t *idstart;
|
||||
size_t idlen;
|
||||
|
||||
unsigned char *name = NULL;
|
||||
utf8_t *name = NULL;
|
||||
size_t namelen = 0;
|
||||
|
||||
//printf("parseSections('%s')\n", comment);
|
||||
p = comment;
|
||||
while (*p)
|
||||
{
|
||||
unsigned char *pstart0 = p;
|
||||
utf8_t *pstart0 = p;
|
||||
p = skipwhitespace(p);
|
||||
pstart = p;
|
||||
pend = p;
|
||||
@@ -1263,7 +1296,7 @@ void DocComment::parseSections(unsigned char *comment)
|
||||
|
||||
if (!inCode && isIdStart(p))
|
||||
{
|
||||
unsigned char *q = p + utfStride(p);
|
||||
utf8_t *q = p + utfStride(p);
|
||||
while (isIdTail(q))
|
||||
q += utfStride(q);
|
||||
if (*q == ':') // identifier: ends it
|
||||
@@ -1337,7 +1370,7 @@ void DocComment::parseSections(unsigned char *comment)
|
||||
void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
{
|
||||
//printf("DocComment::writeSections()\n");
|
||||
if (sections.dim || s->unittest)
|
||||
if (sections.dim || s->ddocUnittest)
|
||||
{
|
||||
buf->writestring("$(DDOC_SECTIONS \n");
|
||||
for (size_t i = 0; i < sections.dim; i++)
|
||||
@@ -1353,12 +1386,12 @@ void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
buf->writestring("$(DDOC_SUMMARY ");
|
||||
size_t o = buf->offset;
|
||||
buf->write(sec->body, sec->bodylen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
escapeStrayParenthesis(buf, o, s);
|
||||
highlightText(sc, s, buf, o);
|
||||
buf->writestring(")\n");
|
||||
}
|
||||
}
|
||||
if (s->unittest)
|
||||
if (s->ddocUnittest)
|
||||
emitUnittestComment(sc, s, 0);
|
||||
buf->writestring(")\n");
|
||||
}
|
||||
@@ -1395,10 +1428,10 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
buf->writestring("$(DDOC_SECTION_H ");
|
||||
size_t o = buf->offset;
|
||||
for (size_t u = 0; u < namelen; u++)
|
||||
{ unsigned char c = name[u];
|
||||
{ utf8_t c = name[u];
|
||||
buf->writeByte((c == '_') ? ' ' : c);
|
||||
}
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
escapeStrayParenthesis(buf, o, s);
|
||||
buf->writestring(":)\n");
|
||||
}
|
||||
else
|
||||
@@ -1408,7 +1441,7 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
L1:
|
||||
size_t o = buf->offset;
|
||||
buf->write(body, bodylen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
escapeStrayParenthesis(buf, o, s);
|
||||
highlightText(sc, s, buf, o);
|
||||
buf->writestring(")\n");
|
||||
}
|
||||
@@ -1418,20 +1451,20 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
|
||||
void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
{
|
||||
unsigned char *p = body;
|
||||
utf8_t *p = body;
|
||||
size_t len = bodylen;
|
||||
unsigned char *pend = p + len;
|
||||
utf8_t *pend = p + len;
|
||||
|
||||
unsigned char *tempstart;
|
||||
utf8_t *tempstart;
|
||||
size_t templen;
|
||||
|
||||
unsigned char *namestart;
|
||||
utf8_t *namestart;
|
||||
size_t namelen = 0; // !=0 if line continuation
|
||||
|
||||
unsigned char *textstart;
|
||||
utf8_t *textstart;
|
||||
size_t textlen;
|
||||
|
||||
size_t o;
|
||||
size_t o, paramcount = 0;
|
||||
Parameter *arg;
|
||||
|
||||
buf->writestring("$(DDOC_PARAMS \n");
|
||||
@@ -1481,23 +1514,37 @@ void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
|
||||
L1:
|
||||
//printf("param '%.*s' = '%.*s'\n", namelen, namestart, textlen, textstart);
|
||||
++paramcount;
|
||||
HdrGenState hgs;
|
||||
buf->writestring("$(DDOC_PARAM_ROW ");
|
||||
buf->writestring("$(DDOC_PARAM_ID ");
|
||||
o = buf->offset;
|
||||
arg = isFunctionParameter(s, namestart, namelen);
|
||||
if (arg && arg->type && arg->ident)
|
||||
{
|
||||
arg->type->toCBuffer(buf, arg->ident, &hgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isTemplateParameter(s, namestart, namelen))
|
||||
{
|
||||
// 10236: Don't count template parameters for params check
|
||||
--paramcount;
|
||||
}
|
||||
else if (!arg)
|
||||
{
|
||||
warning(s->loc, "Ddoc: function declaration has no parameter '%.*s'", namelen, namestart);
|
||||
}
|
||||
buf->write(namestart, namelen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
}
|
||||
escapeStrayParenthesis(buf, o, s);
|
||||
highlightCode(sc, s, buf, o, false);
|
||||
buf->writestring(")\n");
|
||||
|
||||
buf->writestring("$(DDOC_PARAM_DESC ");
|
||||
o = buf->offset;
|
||||
buf->write(textstart, textlen);
|
||||
escapeStrayParenthesis(buf, o, s->loc);
|
||||
escapeStrayParenthesis(buf, o, s);
|
||||
highlightText(sc, s, buf, o);
|
||||
buf->writestring(")");
|
||||
buf->writestring(")\n");
|
||||
@@ -1530,6 +1577,16 @@ void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
if (namelen)
|
||||
goto L1; // write out last one
|
||||
buf->writestring(")\n");
|
||||
|
||||
TypeFunction *tf = isTypeFunction(s);
|
||||
if (tf)
|
||||
{
|
||||
size_t pcount = tf->parameters ? tf->parameters->dim : 0;
|
||||
if (pcount != paramcount)
|
||||
{
|
||||
warning(s->loc, "Ddoc: parameter count mismatch");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
@@ -1549,19 +1606,19 @@ void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf)
|
||||
* name2 = value2
|
||||
*/
|
||||
|
||||
void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, size_t mlen)
|
||||
void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, utf8_t *m, size_t mlen)
|
||||
{
|
||||
unsigned char *p = m;
|
||||
utf8_t *p = m;
|
||||
size_t len = mlen;
|
||||
unsigned char *pend = p + len;
|
||||
utf8_t *pend = p + len;
|
||||
|
||||
unsigned char *tempstart;
|
||||
utf8_t *tempstart;
|
||||
size_t templen;
|
||||
|
||||
unsigned char *namestart;
|
||||
utf8_t *namestart;
|
||||
size_t namelen = 0; // !=0 if line continuation
|
||||
|
||||
unsigned char *textstart;
|
||||
utf8_t *textstart;
|
||||
size_t textlen;
|
||||
|
||||
while (p < pend)
|
||||
@@ -1674,7 +1731,7 @@ Ldone:
|
||||
* by whitespace and/or commas.
|
||||
*/
|
||||
|
||||
void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, size_t textlen)
|
||||
void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t textlen)
|
||||
{ Escape *escapetable = *pescapetable;
|
||||
|
||||
if (!escapetable)
|
||||
@@ -1683,8 +1740,8 @@ void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, s
|
||||
*pescapetable = escapetable;
|
||||
}
|
||||
//printf("parseEscapes('%.*s') pescapetable = %p\n", textlen, textstart, pescapetable);
|
||||
unsigned char *p = textstart;
|
||||
unsigned char *pend = p + textlen;
|
||||
utf8_t *p = textstart;
|
||||
utf8_t *pend = p + textlen;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -1698,9 +1755,9 @@ void DocComment::parseEscapes(Escape **pescapetable, unsigned char *textstart, s
|
||||
}
|
||||
if (p[0] != '/' || p[2] != '/')
|
||||
return;
|
||||
unsigned char c = p[1];
|
||||
utf8_t c = p[1];
|
||||
p += 3;
|
||||
unsigned char *start = p;
|
||||
utf8_t *start = p;
|
||||
while (1)
|
||||
{
|
||||
if (p >= pend)
|
||||
@@ -1746,11 +1803,11 @@ int icmp(const char *stringz, void *s, size_t slen)
|
||||
* Return !=0 if comment consists entirely of "ditto".
|
||||
*/
|
||||
|
||||
int isDitto(unsigned char *comment)
|
||||
int isDitto(utf8_t *comment)
|
||||
{
|
||||
if (comment)
|
||||
{
|
||||
unsigned char *p = skipwhitespace(comment);
|
||||
utf8_t *p = skipwhitespace(comment);
|
||||
|
||||
if (Port::memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0)
|
||||
return 1;
|
||||
@@ -1762,7 +1819,7 @@ int isDitto(unsigned char *comment)
|
||||
* Skip white space.
|
||||
*/
|
||||
|
||||
unsigned char *skipwhitespace(unsigned char *p)
|
||||
utf8_t *skipwhitespace(utf8_t *p)
|
||||
{
|
||||
for (; 1; p++)
|
||||
{ switch (*p)
|
||||
@@ -1791,7 +1848,7 @@ size_t skiptoident(OutBuffer *buf, size_t i)
|
||||
{ dchar_t c;
|
||||
|
||||
size_t oi = i;
|
||||
if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c))
|
||||
if (utf_decodeChar((utf8_t *)buf->data, buf->offset, &i, &c))
|
||||
/* Ignore UTF errors, but still consume input
|
||||
*/
|
||||
break;
|
||||
@@ -1818,7 +1875,7 @@ size_t skippastident(OutBuffer *buf, size_t i)
|
||||
{ dchar_t c;
|
||||
|
||||
size_t oi = i;
|
||||
if (utf_decodeChar((unsigned char *)buf->data, buf->offset, &i, &c))
|
||||
if (utf_decodeChar((utf8_t *)buf->data, buf->offset, &i, &c))
|
||||
/* Ignore UTF errors, but still consume input
|
||||
*/
|
||||
break;
|
||||
@@ -1846,7 +1903,7 @@ size_t skippastident(OutBuffer *buf, size_t i)
|
||||
|
||||
size_t skippastURL(OutBuffer *buf, size_t i)
|
||||
{ size_t length = buf->offset - i;
|
||||
unsigned char *p = &buf->data[i];
|
||||
utf8_t *p = &buf->data[i];
|
||||
size_t j;
|
||||
unsigned sawdot = 0;
|
||||
|
||||
@@ -1862,7 +1919,7 @@ size_t skippastURL(OutBuffer *buf, size_t i)
|
||||
goto Lno;
|
||||
|
||||
for (; j < length; j++)
|
||||
{ unsigned char c = p[j];
|
||||
{ utf8_t c = p[j];
|
||||
if (isalnum(c))
|
||||
continue;
|
||||
if (c == '-' || c == '_' || c == '?' ||
|
||||
@@ -1888,7 +1945,7 @@ Lno:
|
||||
/****************************************************
|
||||
*/
|
||||
|
||||
int isKeyword(unsigned char *p, size_t len)
|
||||
int isKeyword(utf8_t *p, size_t len)
|
||||
{
|
||||
static const char *table[] = { "true", "false", "null" };
|
||||
|
||||
@@ -1903,10 +1960,17 @@ int isKeyword(unsigned char *p, size_t len)
|
||||
/****************************************************
|
||||
*/
|
||||
|
||||
Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, size_t len)
|
||||
TypeFunction *isTypeFunction(Dsymbol *s)
|
||||
{
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
|
||||
/* Check whether s refers to an eponymous function template.
|
||||
*/
|
||||
if (f == NULL && s->isTemplateDeclaration() && s->isTemplateDeclaration()->onemember)
|
||||
{
|
||||
f = s->isTemplateDeclaration()->onemember->isFuncDeclaration();
|
||||
}
|
||||
|
||||
/* f->type may be NULL for template members.
|
||||
*/
|
||||
if (f && f->type)
|
||||
@@ -1919,15 +1983,45 @@ Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, size_t len)
|
||||
else
|
||||
tf = (TypeFunction *)f->type;
|
||||
|
||||
if (tf->parameters)
|
||||
{
|
||||
for (size_t k = 0; k < tf->parameters->dim; k++)
|
||||
{ Parameter *arg = (*tf->parameters)[k];
|
||||
return tf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
/****************************************************
|
||||
*/
|
||||
|
||||
Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len)
|
||||
{
|
||||
TypeFunction *tf = isTypeFunction(s);
|
||||
if (tf && tf->parameters)
|
||||
{
|
||||
for (size_t k = 0; k < tf->parameters->dim; k++)
|
||||
{
|
||||
Parameter *arg = (*tf->parameters)[k];
|
||||
if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
*/
|
||||
|
||||
TemplateParameter *isTemplateParameter(Dsymbol *s, utf8_t *p, size_t len)
|
||||
{
|
||||
TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||
if (td && td->origParameters)
|
||||
{
|
||||
for (size_t k = 0; k < td->origParameters->dim; k++)
|
||||
{
|
||||
TemplateParameter *arg = (*td->origParameters)[k];
|
||||
if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1943,7 +2037,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
||||
//printf("highlightText()\n");
|
||||
const char *sid = s->ident->toChars();
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
unsigned char *p;
|
||||
utf8_t *p;
|
||||
const char *se;
|
||||
|
||||
int leadingBlank = 1;
|
||||
@@ -1955,7 +2049,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
||||
size_t iLineStart = offset;
|
||||
|
||||
for (size_t i = offset; i < buf->offset; i++)
|
||||
{ unsigned char c = buf->data[i];
|
||||
{ utf8_t c = buf->data[i];
|
||||
|
||||
Lcont:
|
||||
switch (c)
|
||||
@@ -1970,7 +2064,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
||||
{
|
||||
static char blankline[] = "$(DDOC_BLANKLINE)\n";
|
||||
|
||||
i = buf->insert(i, blankline, sizeof(blankline) - 1);
|
||||
i = buf->insert(i, blankline, strlen(blankline));
|
||||
}
|
||||
leadingBlank = 1;
|
||||
iLineStart = i + 1;
|
||||
@@ -2126,13 +2220,13 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
||||
|
||||
// Remove leading indentations from all lines
|
||||
bool lineStart = true;
|
||||
unsigned char *endp = codebuf.data + codebuf.offset;
|
||||
for (unsigned char *p = codebuf.data; p < endp; )
|
||||
utf8_t *endp = codebuf.data + codebuf.offset;
|
||||
for (utf8_t *p = codebuf.data; p < endp; )
|
||||
{
|
||||
if (lineStart)
|
||||
{
|
||||
size_t j = codeIndent;
|
||||
unsigned char *q = p;
|
||||
utf8_t *q = p;
|
||||
while (j-- > 0 && q < endp && isIndentWS(q))
|
||||
++q;
|
||||
codebuf.remove(p - codebuf.data, q - p);
|
||||
@@ -2158,7 +2252,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
||||
|
||||
inCode = 1;
|
||||
codeIndent = istart - iLineStart; // save indent count
|
||||
i = buf->insert(i, pre, sizeof(pre) - 1);
|
||||
i = buf->insert(i, pre, strlen(pre));
|
||||
iCodeStart = i;
|
||||
i--; // place i on >
|
||||
leadingBlank = true;
|
||||
@@ -2237,7 +2331,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
|
||||
|
||||
//printf("highlightCode(s = '%s', kind = %s)\n", sid, s->kind());
|
||||
for (size_t i = offset; i < buf->offset; i++)
|
||||
{ unsigned char c = buf->data[i];
|
||||
{ utf8_t c = buf->data[i];
|
||||
const char *se;
|
||||
|
||||
se = sc->module->escapetable->escapeChar(c);
|
||||
@@ -2276,7 +2370,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an
|
||||
/****************************************
|
||||
*/
|
||||
|
||||
void highlightCode3(Scope *sc, OutBuffer *buf, unsigned char *p, unsigned char *pend)
|
||||
void highlightCode3(Scope *sc, OutBuffer *buf, utf8_t *p, utf8_t *pend)
|
||||
{
|
||||
for (; p < pend; p++)
|
||||
{ const char *s = sc->module->escapetable->escapeChar(*p);
|
||||
@@ -2294,13 +2388,13 @@ void highlightCode3(Scope *sc, OutBuffer *buf, unsigned char *p, unsigned char *
|
||||
|
||||
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
||||
{
|
||||
char *sid = s->ident->toChars();
|
||||
const char *sid = s->ident->toChars();
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
unsigned errorsave = global.errors;
|
||||
Lexer lex(NULL, buf->data, 0, buf->offset - 1, 0, 1);
|
||||
Token tok;
|
||||
OutBuffer res;
|
||||
unsigned char *lastp = buf->data;
|
||||
utf8_t *lastp = buf->data;
|
||||
const char *highlight;
|
||||
|
||||
if (s->isModule() && ((Module *)s)->isDocFile)
|
||||
@@ -2348,10 +2442,16 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
|
||||
break;
|
||||
}
|
||||
if (highlight)
|
||||
{
|
||||
res.writestring(highlight);
|
||||
highlightCode3(sc, &res, tok.ptr, lex.p);
|
||||
if (highlight)
|
||||
size_t o = res.offset;
|
||||
highlightCode3(sc, &res, tok.ptr, lex.p);
|
||||
if (tok.value == TOKcomment || tok.value == TOKstring)
|
||||
escapeDdocString(&res, o); // Bugzilla 7656, 7715, and 10519
|
||||
res.writeByte(')');
|
||||
}
|
||||
else
|
||||
highlightCode3(sc, &res, tok.ptr, lex.p);
|
||||
if (tok.value == TOKeof)
|
||||
break;
|
||||
lastp = lex.p;
|
||||
@@ -2396,7 +2496,7 @@ const char *Escape::escapeChar(unsigned c)
|
||||
* Determine if p points to the start of an identifier.
|
||||
*/
|
||||
|
||||
int isIdStart(unsigned char *p)
|
||||
int isIdStart(utf8_t *p)
|
||||
{
|
||||
unsigned c = *p;
|
||||
if (isalpha(c) || c == '_')
|
||||
@@ -2415,7 +2515,7 @@ int isIdStart(unsigned char *p)
|
||||
* Determine if p points to the rest of an identifier.
|
||||
*/
|
||||
|
||||
int isIdTail(unsigned char *p)
|
||||
int isIdTail(utf8_t *p)
|
||||
{
|
||||
unsigned c = *p;
|
||||
if (isalnum(c) || c == '_')
|
||||
@@ -2434,7 +2534,7 @@ int isIdTail(unsigned char *p)
|
||||
* Determine if p points to the indentation space.
|
||||
*/
|
||||
|
||||
int isIndentWS(unsigned char *p)
|
||||
int isIndentWS(utf8_t *p)
|
||||
{
|
||||
return (*p == ' ') || (*p == '\t');
|
||||
}
|
||||
@@ -2443,7 +2543,7 @@ int isIndentWS(unsigned char *p)
|
||||
* Return number of bytes in UTF character.
|
||||
*/
|
||||
|
||||
int utfStride(unsigned char *p)
|
||||
int utfStride(utf8_t *p)
|
||||
{
|
||||
unsigned c = *p;
|
||||
if (c < 0x80)
|
||||
|
||||
+115
-157
@@ -53,10 +53,11 @@ Dsymbol::Dsymbol()
|
||||
this->loc = Loc();
|
||||
this->comment = NULL;
|
||||
this->scope = NULL;
|
||||
this->semanticRun = PASSinit;
|
||||
this->errors = false;
|
||||
this->depmsg = NULL;
|
||||
this->userAttributes = NULL;
|
||||
this->unittest = NULL;
|
||||
this->ddocUnittest = NULL;
|
||||
#if IN_LLVM
|
||||
this->llvmInternal = LLVMnone;
|
||||
#endif
|
||||
@@ -74,25 +75,25 @@ Dsymbol::Dsymbol(Identifier *ident)
|
||||
this->loc = Loc();
|
||||
this->comment = NULL;
|
||||
this->scope = NULL;
|
||||
this->semanticRun = PASSinit;
|
||||
this->errors = false;
|
||||
this->depmsg = NULL;
|
||||
this->userAttributes = NULL;
|
||||
this->unittest = NULL;
|
||||
this->ddocUnittest = NULL;
|
||||
#if IN_LLVM
|
||||
this->llvmInternal = LLVMnone;
|
||||
#endif
|
||||
}
|
||||
|
||||
int Dsymbol::equals(Object *o)
|
||||
{ Dsymbol *s;
|
||||
|
||||
bool Dsymbol::equals(RootObject *o)
|
||||
{
|
||||
if (this == o)
|
||||
return TRUE;
|
||||
s = (Dsymbol *)(o);
|
||||
return true;
|
||||
Dsymbol *s = (Dsymbol *)(o);
|
||||
// Overload sets don't have an ident
|
||||
if (s && ident && s->ident && ident->equals(s->ident))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
@@ -112,23 +113,23 @@ Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
|
||||
/**************************************
|
||||
* Determine if this symbol is only one.
|
||||
* Returns:
|
||||
* FALSE, *ps = NULL: There are 2 or more symbols
|
||||
* TRUE, *ps = NULL: There are zero symbols
|
||||
* TRUE, *ps = symbol: The one and only one symbol
|
||||
* false, *ps = NULL: There are 2 or more symbols
|
||||
* true, *ps = NULL: There are zero symbols
|
||||
* true, *ps = symbol: The one and only one symbol
|
||||
*/
|
||||
|
||||
int Dsymbol::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
bool Dsymbol::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
//printf("Dsymbol::oneMember()\n");
|
||||
*ps = this;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
|
||||
*/
|
||||
|
||||
int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident)
|
||||
bool Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
//printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
|
||||
Dsymbol *s = NULL;
|
||||
@@ -138,46 +139,61 @@ int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident)
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *sx = (*members)[i];
|
||||
|
||||
int x = sx->oneMember(ps, ident);
|
||||
bool x = sx->oneMember(ps, ident);
|
||||
//printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
|
||||
if (!x)
|
||||
{
|
||||
//printf("\tfalse 1\n");
|
||||
assert(*ps == NULL);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
if (*ps)
|
||||
{
|
||||
if (ident)
|
||||
{
|
||||
if (!(*ps)->ident || !(*ps)->ident->equals(ident))
|
||||
continue;
|
||||
}
|
||||
assert(ident);
|
||||
if (!(*ps)->ident || !(*ps)->ident->equals(ident))
|
||||
continue;
|
||||
if (!s)
|
||||
s = *ps;
|
||||
else if (s->isOverloadable() && (*ps)->isOverloadable())
|
||||
; // keep head of overload set
|
||||
{
|
||||
// keep head of overload set
|
||||
FuncDeclaration *f1 = s->isFuncDeclaration();
|
||||
FuncDeclaration *f2 = (*ps)->isFuncDeclaration();
|
||||
if (f1 && f2)
|
||||
{
|
||||
assert(!f1->isFuncAliasDeclaration());
|
||||
assert(!f2->isFuncAliasDeclaration());
|
||||
for (; f1 != f2; f1 = f1->overnext0)
|
||||
{
|
||||
if (f1->overnext0 == NULL)
|
||||
{
|
||||
f1->overnext0 = f2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // more than one symbol
|
||||
{ *ps = NULL;
|
||||
//printf("\tfalse 2\n");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*ps = s; // s is the one symbol, NULL if none
|
||||
//printf("\ttrue\n");
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Is Dsymbol a variable that contains pointers?
|
||||
*/
|
||||
|
||||
int Dsymbol::hasPointers()
|
||||
bool Dsymbol::hasPointers()
|
||||
{
|
||||
//printf("Dsymbol::hasPointers() %s\n", toChars());
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Dsymbol::hasStaticCtorOrDtor()
|
||||
@@ -190,6 +206,11 @@ void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool i
|
||||
{
|
||||
}
|
||||
|
||||
Identifier *Dsymbol::getIdent()
|
||||
{
|
||||
return ident;
|
||||
}
|
||||
|
||||
char *Dsymbol::toChars()
|
||||
{
|
||||
return ident ? ident->toChars() : (char *)"__anonymous";
|
||||
@@ -315,9 +336,9 @@ TemplateInstance *Dsymbol::isSpeculative()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Dsymbol::isAnonymous()
|
||||
bool Dsymbol::isAnonymous()
|
||||
{
|
||||
return ident ? 0 : 1;
|
||||
return ident == NULL;
|
||||
}
|
||||
|
||||
/*************************************
|
||||
@@ -343,10 +364,6 @@ void Dsymbol::importAll(Scope *sc)
|
||||
* Does semantic analysis on the public face of declarations.
|
||||
*/
|
||||
|
||||
void Dsymbol::semantic0(Scope *sc)
|
||||
{
|
||||
}
|
||||
|
||||
void Dsymbol::semantic(Scope *sc)
|
||||
{
|
||||
error("%p has no semantic routine", this);
|
||||
@@ -414,8 +431,7 @@ void *symbol_search_fp(void *arg, const char *seed)
|
||||
assert(id);
|
||||
|
||||
Dsymbol *s = (Dsymbol *)arg;
|
||||
Module::clearCache();
|
||||
return s->search(Loc(), id, 4|2);
|
||||
return (void *)s->search(Loc(), id, 4|2);
|
||||
}
|
||||
|
||||
Dsymbol *Dsymbol::search_correct(Identifier *ident)
|
||||
@@ -423,7 +439,7 @@ Dsymbol *Dsymbol::search_correct(Identifier *ident)
|
||||
if (global.gag)
|
||||
return NULL; // don't do it for speculative compiles; too time consuming
|
||||
|
||||
return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, this, idchars);
|
||||
return (Dsymbol *)speller(ident->toChars(), &symbol_search_fp, (void *)this, idchars);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
@@ -433,7 +449,7 @@ Dsymbol *Dsymbol::search_correct(Identifier *ident)
|
||||
* symbol found, NULL if not
|
||||
*/
|
||||
|
||||
Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Object *id)
|
||||
Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
|
||||
{
|
||||
//printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
|
||||
Dsymbol *s = toAlias();
|
||||
@@ -483,10 +499,10 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Object *id)
|
||||
return sm;
|
||||
}
|
||||
|
||||
int Dsymbol::overloadInsert(Dsymbol *s)
|
||||
bool Dsymbol::overloadInsert(Dsymbol *s)
|
||||
{
|
||||
//printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
@@ -500,9 +516,9 @@ unsigned Dsymbol::size(Loc loc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Dsymbol::isforwardRef()
|
||||
bool Dsymbol::isforwardRef()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
AggregateDeclaration *Dsymbol::isThis()
|
||||
@@ -537,14 +553,14 @@ void Dsymbol::defineRef(Dsymbol *s)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int Dsymbol::isExport()
|
||||
bool Dsymbol::isExport()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Dsymbol::isImportedSymbol()
|
||||
bool Dsymbol::isImportedSymbol()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Dsymbol::isDeprecated()
|
||||
@@ -553,14 +569,14 @@ bool Dsymbol::isDeprecated()
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int Dsymbol::isOverloadable()
|
||||
bool Dsymbol::isOverloadable()
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Dsymbol::hasOverloads()
|
||||
bool Dsymbol::hasOverloads()
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -582,9 +598,9 @@ Type *Dsymbol::getType()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Dsymbol::needThis()
|
||||
bool Dsymbol::needThis()
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||
@@ -756,7 +772,7 @@ Module *Dsymbol::getAccessModule()
|
||||
/*************************************
|
||||
*/
|
||||
|
||||
enum PROT Dsymbol::prot()
|
||||
PROT Dsymbol::prot()
|
||||
{
|
||||
return PROTpublic;
|
||||
}
|
||||
@@ -790,7 +806,7 @@ Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a)
|
||||
* Ignore NULL comments.
|
||||
*/
|
||||
|
||||
void Dsymbol::addComment(unsigned char *comment)
|
||||
void Dsymbol::addComment(utf8_t *comment)
|
||||
{
|
||||
//if (comment)
|
||||
//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
|
||||
@@ -858,35 +874,44 @@ Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
|
||||
return sd;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* This function is #1 on the list of functions that eat cpu time.
|
||||
* Be very, very careful about slowing it down.
|
||||
*/
|
||||
|
||||
Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
//printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
|
||||
//if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;
|
||||
|
||||
// Look in symbols declared in this module
|
||||
Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
|
||||
//printf("\ts = %p, imports = %p, %d\n", s, imports, imports ? imports->dim : 0);
|
||||
if (s)
|
||||
Dsymbol *s1 = symtab ? symtab->lookup(ident) : NULL;
|
||||
//printf("\ts1 = %p, imports = %p, %d\n", s1, imports, imports ? imports->dim : 0);
|
||||
if (s1)
|
||||
{
|
||||
//printf("\ts = '%s.%s'\n",toChars(),s->toChars());
|
||||
//printf("\ts = '%s.%s'\n",toChars(),s1->toChars());
|
||||
return s1;
|
||||
}
|
||||
else if (imports)
|
||||
else if (!imports)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
Dsymbol *s = NULL;
|
||||
OverloadSet *a = NULL;
|
||||
|
||||
// Look in imported modules
|
||||
for (size_t i = 0; i < imports->dim; i++)
|
||||
{ Dsymbol *ss = (*imports)[i];
|
||||
Dsymbol *s2;
|
||||
|
||||
{
|
||||
// If private import, don't search it
|
||||
if (flags & 1 && prots[i] == PROTprivate)
|
||||
continue;
|
||||
|
||||
Dsymbol *ss = (*imports)[i];
|
||||
|
||||
//printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
|
||||
/* Don't find private members if ss is a module
|
||||
*/
|
||||
s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
|
||||
Dsymbol *s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
|
||||
if (!s)
|
||||
s = s2;
|
||||
else if (s2 && s != s2)
|
||||
@@ -931,7 +956,10 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
*/
|
||||
if (s2->isOverloadable() && (a || s->isOverloadable()))
|
||||
{ if (!a)
|
||||
{
|
||||
a = new OverloadSet(s->ident);
|
||||
a->parent = this;
|
||||
}
|
||||
/* Don't add to a[] if s2 is alias of previous sym
|
||||
*/
|
||||
for (size_t j = 0; j < a->a.dim; j++)
|
||||
@@ -968,33 +996,17 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
|
||||
if (s)
|
||||
{
|
||||
if (!(flags & 2))
|
||||
{ Declaration *d = s->isDeclaration();
|
||||
if (d && d->protection == PROTprivate &&
|
||||
!d->parent->isTemplateMixin())
|
||||
error(loc, "%s is private", d->toPrettyChars());
|
||||
|
||||
AggregateDeclaration *ad = s->isAggregateDeclaration();
|
||||
if (ad && ad->protection == PROTprivate &&
|
||||
!ad->parent->isTemplateMixin())
|
||||
error(loc, "%s is private", ad->toPrettyChars());
|
||||
|
||||
EnumDeclaration *ed = s->isEnumDeclaration();
|
||||
if (ed && ed->protection == PROTprivate &&
|
||||
!ed->parent->isTemplateMixin())
|
||||
error(loc, "%s is private", ed->toPrettyChars());
|
||||
|
||||
TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||
if (td && td->protection == PROTprivate &&
|
||||
!td->parent->isTemplateMixin())
|
||||
error(loc, "%s is private", td->toPrettyChars());
|
||||
if (!(flags & 2) && s->prot() == PROTprivate && !s->parent->isTemplateMixin())
|
||||
{
|
||||
if (!s->isImport())
|
||||
error(loc, "%s %s is private", s->kind(), s->toPrettyChars());
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void ScopeDsymbol::importScope(Dsymbol *s, enum PROT protection)
|
||||
void ScopeDsymbol::importScope(Dsymbol *s, PROT protection)
|
||||
{
|
||||
//printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
|
||||
|
||||
@@ -1021,7 +1033,7 @@ void ScopeDsymbol::importScope(Dsymbol *s, enum PROT protection)
|
||||
}
|
||||
}
|
||||
|
||||
int ScopeDsymbol::isforwardRef()
|
||||
bool ScopeDsymbol::isforwardRef()
|
||||
{
|
||||
return (members == NULL);
|
||||
}
|
||||
@@ -1251,7 +1263,24 @@ WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
|
||||
Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
// Acts as proxy to the with class declaration
|
||||
return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
|
||||
Dsymbol *s = NULL;
|
||||
Expression *eold = NULL;
|
||||
for (Expression *e = withstate->exp; e != eold; e = resolveAliasThis(scope, e))
|
||||
{
|
||||
Type *t = e->type->toBasetype();
|
||||
if (t->ty == Taarray)
|
||||
s = ((TypeAArray *)t)->getImpl();
|
||||
else
|
||||
s = t->toDsymbol(NULL);
|
||||
if (s)
|
||||
{
|
||||
s = s->search(loc, ident, 0);
|
||||
if (s)
|
||||
return s;
|
||||
}
|
||||
eold = e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************** ArrayScopeSymbol ******************************/
|
||||
@@ -1398,29 +1427,6 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
return NULL;
|
||||
s = s->toAlias();
|
||||
|
||||
if (ce->hasSideEffect())
|
||||
{
|
||||
/* Even if opDollar is needed, 'ce' should be evaluate only once. So
|
||||
* Rewrite:
|
||||
* ce.opIndex( ... use of $ ... )
|
||||
* ce.opSlice( ... use of $ ... )
|
||||
* as:
|
||||
* (ref __dop = ce, __dop).opIndex( ... __dop.opDollar ...)
|
||||
* (ref __dop = ce, __dop).opSlice( ... __dop.opDollar ...)
|
||||
*/
|
||||
Identifier *id = Lexer::uniqueId("__dop");
|
||||
ExpInitializer *ei = new ExpInitializer(loc, ce);
|
||||
VarDeclaration *v = new VarDeclaration(loc, NULL, id, ei);
|
||||
v->storage_class |= STCctfe | STCforeach | STCref;
|
||||
DeclarationExp *de = new DeclarationExp(loc, v);
|
||||
VarExp *ve = new VarExp(loc, v);
|
||||
v->semantic(sc);
|
||||
de->type = ce->type;
|
||||
ve->type = ce->type;
|
||||
((UnaExp *)exp)->e1 = new CommaExp(loc, de, ve);
|
||||
ce = ve;
|
||||
}
|
||||
|
||||
Expression *e = NULL;
|
||||
// Check for multi-dimensional opDollar(dim) template.
|
||||
if (TemplateDeclaration *td = s->isTemplateDeclaration())
|
||||
@@ -1492,90 +1498,42 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
|
||||
|
||||
DsymbolTable::DsymbolTable()
|
||||
{
|
||||
#if STRINGTABLE
|
||||
tab = new StringTable;
|
||||
tab->init();
|
||||
#else
|
||||
tab = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
DsymbolTable::~DsymbolTable()
|
||||
{
|
||||
#if STRINGTABLE
|
||||
delete tab;
|
||||
#endif
|
||||
}
|
||||
|
||||
Dsymbol *DsymbolTable::lookup(Identifier *ident)
|
||||
{
|
||||
#if STRINGTABLE
|
||||
#ifdef DEBUG
|
||||
assert(ident);
|
||||
assert(tab);
|
||||
#endif
|
||||
//printf("DsymbolTable::lookup(%s)\n", (char*)ident->string);
|
||||
StringValue *sv = tab->lookup((char*)ident->string, ident->len);
|
||||
return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
|
||||
#else
|
||||
//printf("DsymbolTable::lookup(%s)\n", (char*)ident->string);
|
||||
return (Dsymbol *)_aaGetRvalue(tab, ident);
|
||||
#endif
|
||||
}
|
||||
|
||||
Dsymbol *DsymbolTable::insert(Dsymbol *s)
|
||||
{
|
||||
//printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
|
||||
Identifier *ident = s->ident;
|
||||
#if STRINGTABLE
|
||||
#ifdef DEBUG
|
||||
assert(ident);
|
||||
assert(tab);
|
||||
#endif
|
||||
StringValue *sv = tab->insert(ident->toChars(), ident->len);
|
||||
if (!sv)
|
||||
return NULL; // already in table
|
||||
sv->ptrvalue = s;
|
||||
return s;
|
||||
#else
|
||||
Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident);
|
||||
if (*ps)
|
||||
return NULL; // already in table
|
||||
*ps = s;
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
|
||||
{
|
||||
//printf("DsymbolTable::insert()\n");
|
||||
#if STRINGTABLE
|
||||
StringValue *sv = tab->insert(ident->toChars(), ident->len);
|
||||
if (!sv)
|
||||
return NULL; // already in table
|
||||
sv->ptrvalue = s;
|
||||
return s;
|
||||
#else
|
||||
Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident);
|
||||
if (*ps)
|
||||
return NULL; // already in table
|
||||
*ps = s;
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
Dsymbol *DsymbolTable::update(Dsymbol *s)
|
||||
{
|
||||
Identifier *ident = s->ident;
|
||||
#if STRINGTABLE
|
||||
StringValue *sv = tab->update(ident->toChars(), ident->len);
|
||||
sv->ptrvalue = s;
|
||||
return s;
|
||||
#else
|
||||
Dsymbol **ps = (Dsymbol **)_aaGet(&tab, ident);
|
||||
*ps = s;
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
+88
-79
@@ -29,66 +29,65 @@
|
||||
#include "../ir/irdsymbol.h"
|
||||
#endif
|
||||
|
||||
struct Identifier;
|
||||
class Identifier;
|
||||
struct Scope;
|
||||
struct DsymbolTable;
|
||||
struct Declaration;
|
||||
struct ThisDeclaration;
|
||||
struct TupleDeclaration;
|
||||
struct TypedefDeclaration;
|
||||
struct AliasDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct EnumDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct InterfaceDeclaration;
|
||||
struct StructDeclaration;
|
||||
struct UnionDeclaration;
|
||||
struct FuncDeclaration;
|
||||
struct FuncAliasDeclaration;
|
||||
struct FuncLiteralDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct PostBlitDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct StaticCtorDeclaration;
|
||||
struct StaticDtorDeclaration;
|
||||
struct SharedStaticCtorDeclaration;
|
||||
struct SharedStaticDtorDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct UnitTestDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct AttribDeclaration;
|
||||
class DsymbolTable;
|
||||
class Declaration;
|
||||
class ThisDeclaration;
|
||||
class TypeInfoDeclaration;
|
||||
class TupleDeclaration;
|
||||
class TypedefDeclaration;
|
||||
class AliasDeclaration;
|
||||
class AggregateDeclaration;
|
||||
class EnumDeclaration;
|
||||
class ClassDeclaration;
|
||||
class InterfaceDeclaration;
|
||||
class StructDeclaration;
|
||||
class UnionDeclaration;
|
||||
class FuncDeclaration;
|
||||
class FuncAliasDeclaration;
|
||||
class FuncLiteralDeclaration;
|
||||
class CtorDeclaration;
|
||||
class PostBlitDeclaration;
|
||||
class DtorDeclaration;
|
||||
class StaticCtorDeclaration;
|
||||
class StaticDtorDeclaration;
|
||||
class SharedStaticCtorDeclaration;
|
||||
class SharedStaticDtorDeclaration;
|
||||
class InvariantDeclaration;
|
||||
class UnitTestDeclaration;
|
||||
class NewDeclaration;
|
||||
class VarDeclaration;
|
||||
class AttribDeclaration;
|
||||
#if IN_DMD
|
||||
struct Symbol;
|
||||
#endif
|
||||
struct Package;
|
||||
struct Module;
|
||||
struct Import;
|
||||
struct Type;
|
||||
struct TypeTuple;
|
||||
struct WithStatement;
|
||||
struct LabelDsymbol;
|
||||
struct ScopeDsymbol;
|
||||
struct TemplateDeclaration;
|
||||
struct TemplateInstance;
|
||||
struct TemplateMixin;
|
||||
struct EnumMember;
|
||||
struct ScopeDsymbol;
|
||||
struct WithScopeSymbol;
|
||||
struct ArrayScopeSymbol;
|
||||
struct SymbolDeclaration;
|
||||
struct Expression;
|
||||
struct DeleteDeclaration;
|
||||
class Package;
|
||||
class Module;
|
||||
class Import;
|
||||
class Type;
|
||||
class TypeTuple;
|
||||
class WithStatement;
|
||||
class LabelDsymbol;
|
||||
class ScopeDsymbol;
|
||||
class TemplateDeclaration;
|
||||
class TemplateInstance;
|
||||
class TemplateMixin;
|
||||
class EnumMember;
|
||||
class WithScopeSymbol;
|
||||
class ArrayScopeSymbol;
|
||||
class SymbolDeclaration;
|
||||
class Expression;
|
||||
class DeleteDeclaration;
|
||||
struct HdrGenState;
|
||||
struct OverloadSet;
|
||||
class OverloadSet;
|
||||
struct AA;
|
||||
struct JsonOut;
|
||||
#if IN_LLVM
|
||||
struct TypeInfoDeclaration;
|
||||
struct ClassInfoDeclaration;
|
||||
class TypeInfoDeclaration;
|
||||
class ClassInfoDeclaration;
|
||||
#endif
|
||||
#ifdef IN_GCC
|
||||
union tree_node;
|
||||
typedef union tree_node TYPE;
|
||||
#else
|
||||
struct TYPE;
|
||||
@@ -127,37 +126,42 @@ enum PASS
|
||||
PASSinit, // initial state
|
||||
PASSsemantic, // semantic() started
|
||||
PASSsemanticdone, // semantic() done
|
||||
PASSsemantic2, // semantic2() run
|
||||
PASSsemantic2, // semantic2() started
|
||||
PASSsemantic2done, // semantic2() done
|
||||
PASSsemantic3, // semantic3() started
|
||||
PASSsemantic3done, // semantic3() done
|
||||
PASSinline, // inline started
|
||||
PASSinlinedone, // inline done
|
||||
PASSobj, // toObjFile() run
|
||||
};
|
||||
|
||||
typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
|
||||
|
||||
struct Dsymbol : Object
|
||||
class Dsymbol : public RootObject
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
Dsymbol *parent;
|
||||
#if IN_DMD
|
||||
Symbol *csym; // symbol for code generator
|
||||
Symbol *isym; // import version of csym
|
||||
#endif
|
||||
unsigned char *comment; // documentation comment for this Dsymbol
|
||||
utf8_t *comment; // documentation comment for this Dsymbol
|
||||
Loc loc; // where defined
|
||||
Scope *scope; // !=NULL means context to use for semantic()
|
||||
bool errors; // this symbol failed to pass semantic()
|
||||
PASS semanticRun;
|
||||
char *depmsg; // customized deprecation message
|
||||
Expressions *userAttributes; // user defined attributes from UserAttributeDeclaration
|
||||
UnitTestDeclaration *unittest; // !=NULL means there's a unittest associated with this symbol
|
||||
UnitTestDeclaration *ddocUnittest; // !=NULL means there's a ddoc unittest associated with this symbol (only use this with ddoc)
|
||||
|
||||
Dsymbol();
|
||||
Dsymbol(Identifier *);
|
||||
char *toChars();
|
||||
Loc& getLoc();
|
||||
char *locToChars();
|
||||
int equals(Object *o);
|
||||
int isAnonymous();
|
||||
bool equals(RootObject *o);
|
||||
bool isAnonymous();
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void error(const char *format, ...);
|
||||
void deprecation(Loc loc, const char *format, ...);
|
||||
@@ -170,11 +174,13 @@ struct Dsymbol : Object
|
||||
Dsymbol *toParent2();
|
||||
TemplateInstance *inTemplateInstance();
|
||||
TemplateInstance *isSpeculative();
|
||||
Ungag ungagSpeculative();
|
||||
|
||||
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
|
||||
|
||||
static Dsymbols *arraySyntaxCopy(Dsymbols *a);
|
||||
|
||||
virtual Identifier *getIdent();
|
||||
virtual const char *toPrettyChars();
|
||||
virtual const char *kind();
|
||||
virtual Dsymbol *toAlias(); // resolve real symbol
|
||||
@@ -182,50 +188,49 @@ struct Dsymbol : Object
|
||||
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
virtual void setScope(Scope *sc);
|
||||
virtual void importAll(Scope *sc);
|
||||
virtual void semantic0(Scope *sc);
|
||||
virtual void semantic(Scope *sc);
|
||||
virtual void semantic2(Scope *sc);
|
||||
virtual void semantic3(Scope *sc);
|
||||
virtual void inlineScan();
|
||||
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
Dsymbol *search_correct(Identifier *id);
|
||||
Dsymbol *searchX(Loc loc, Scope *sc, Object *id);
|
||||
virtual int overloadInsert(Dsymbol *s);
|
||||
Dsymbol *searchX(Loc loc, Scope *sc, RootObject *id);
|
||||
virtual bool overloadInsert(Dsymbol *s);
|
||||
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual void toDocBuffer(OutBuffer *buf, Scope *sc);
|
||||
virtual void toJson(JsonOut *json);
|
||||
virtual void jsonProperties(JsonOut *json);
|
||||
virtual unsigned size(Loc loc);
|
||||
virtual int isforwardRef();
|
||||
virtual bool isforwardRef();
|
||||
virtual void defineRef(Dsymbol *s);
|
||||
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
|
||||
AggregateDeclaration *isAggregateMember(); // are we a member of an aggregate?
|
||||
AggregateDeclaration *isAggregateMember2(); // are we a member of an aggregate?
|
||||
ClassDeclaration *isClassMember(); // are we a member of a class?
|
||||
virtual int isExport(); // is Dsymbol exported?
|
||||
virtual int isImportedSymbol(); // is Dsymbol imported?
|
||||
virtual bool isExport(); // is Dsymbol exported?
|
||||
virtual bool isImportedSymbol(); // is Dsymbol imported?
|
||||
virtual bool isDeprecated(); // is Dsymbol deprecated?
|
||||
#if DMDV2
|
||||
virtual int isOverloadable();
|
||||
virtual int hasOverloads();
|
||||
virtual bool isOverloadable();
|
||||
virtual bool hasOverloads();
|
||||
#endif
|
||||
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
||||
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
||||
virtual Type *getType(); // is this a type?
|
||||
virtual const char *mangle(bool isv = false);
|
||||
virtual int needThis(); // need a 'this' pointer?
|
||||
virtual enum PROT prot();
|
||||
virtual bool needThis(); // need a 'this' pointer?
|
||||
virtual PROT prot();
|
||||
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||
virtual int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL);
|
||||
virtual bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
static bool oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident);
|
||||
virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
virtual int hasPointers();
|
||||
virtual bool hasPointers();
|
||||
virtual bool hasStaticCtorOrDtor();
|
||||
virtual void addLocalClass(ClassDeclarations *) { }
|
||||
virtual void checkCtorConstInit() { }
|
||||
|
||||
virtual void addComment(unsigned char *comment);
|
||||
virtual void addComment(utf8_t *comment);
|
||||
virtual void emitComment(Scope *sc);
|
||||
void emitDitto(Scope *sc);
|
||||
|
||||
@@ -251,6 +256,7 @@ struct Dsymbol : Object
|
||||
virtual TemplateMixin *isTemplateMixin() { return NULL; }
|
||||
virtual Declaration *isDeclaration() { return NULL; }
|
||||
virtual ThisDeclaration *isThisDeclaration() { return NULL; }
|
||||
virtual TypeInfoDeclaration *isTypeInfoDeclaration() { return NULL; }
|
||||
virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
|
||||
virtual TypedefDeclaration *isTypedefDeclaration() { return NULL; }
|
||||
virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
|
||||
@@ -283,7 +289,6 @@ struct Dsymbol : Object
|
||||
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
|
||||
virtual OverloadSet *isOverloadSet() { return NULL; }
|
||||
#if IN_LLVM
|
||||
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
|
||||
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
|
||||
|
||||
/// Codegen traversal
|
||||
@@ -298,8 +303,9 @@ struct Dsymbol : Object
|
||||
|
||||
// Dsymbol that generates a scope
|
||||
|
||||
struct ScopeDsymbol : Dsymbol
|
||||
class ScopeDsymbol : public Dsymbol
|
||||
{
|
||||
public:
|
||||
Dsymbols *members; // all Dsymbol's in this scope
|
||||
DsymbolTable *symtab; // members[] sorted into table
|
||||
|
||||
@@ -310,8 +316,8 @@ struct ScopeDsymbol : Dsymbol
|
||||
ScopeDsymbol(Identifier *id);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
void importScope(Dsymbol *s, enum PROT protection);
|
||||
int isforwardRef();
|
||||
void importScope(Dsymbol *s, PROT protection);
|
||||
bool isforwardRef();
|
||||
void defineRef(Dsymbol *s);
|
||||
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
|
||||
Dsymbol *nameCollision(Dsymbol *s);
|
||||
@@ -333,8 +339,9 @@ struct ScopeDsymbol : Dsymbol
|
||||
|
||||
// With statement scope
|
||||
|
||||
struct WithScopeSymbol : ScopeDsymbol
|
||||
class WithScopeSymbol : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
WithStatement *withstate;
|
||||
|
||||
WithScopeSymbol(WithStatement *withstate);
|
||||
@@ -345,8 +352,9 @@ struct WithScopeSymbol : ScopeDsymbol
|
||||
|
||||
// Array Index/Slice scope
|
||||
|
||||
struct ArrayScopeSymbol : ScopeDsymbol
|
||||
class ArrayScopeSymbol : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
Expression *exp; // IndexExp or SliceExp
|
||||
TypeTuple *type; // for tuple[length]
|
||||
TupleDeclaration *td; // for tuples of objects
|
||||
@@ -363,8 +371,9 @@ struct ArrayScopeSymbol : ScopeDsymbol
|
||||
// Overload Sets
|
||||
|
||||
#if DMDV2
|
||||
struct OverloadSet : Dsymbol
|
||||
class OverloadSet : public Dsymbol
|
||||
{
|
||||
public:
|
||||
Dsymbols a; // array of Dsymbols
|
||||
|
||||
OverloadSet(Identifier *ident);
|
||||
@@ -376,12 +385,12 @@ struct OverloadSet : Dsymbol
|
||||
|
||||
// Table of Dsymbol's
|
||||
|
||||
struct DsymbolTable : Object
|
||||
class DsymbolTable : public RootObject
|
||||
{
|
||||
public:
|
||||
AA *tab;
|
||||
|
||||
DsymbolTable();
|
||||
~DsymbolTable();
|
||||
|
||||
// Look up Identifier. Return Dsymbol if found, NULL if not.
|
||||
Dsymbol *lookup(Identifier *ident);
|
||||
|
||||
+3
-1
@@ -11,6 +11,8 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "port.h"
|
||||
|
||||
/*********************************************
|
||||
* Convert from named entity to its encoding.
|
||||
* For reference:
|
||||
@@ -2372,7 +2374,7 @@ static NameId* namesTable[] = {
|
||||
namesS, namesT, namesU, namesV, namesW, namesX, namesY, namesZ, NULL
|
||||
};
|
||||
|
||||
int HtmlNamedEntity(unsigned char *p, size_t length)
|
||||
int HtmlNamedEntity(utf8_t *p, size_t length)
|
||||
{
|
||||
int tableIndex = tolower(*p) - 'a';
|
||||
if (tableIndex >= 0 && tableIndex < 26)
|
||||
|
||||
+400
-236
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -25,6 +25,7 @@
|
||||
EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
|
||||
: ScopeDsymbol(id)
|
||||
{
|
||||
//printf("EnumDeclaration() %s\n", toChars());
|
||||
this->loc = loc;
|
||||
type = new TypeEnum(this);
|
||||
this->memtype = memtype;
|
||||
@@ -35,12 +36,9 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
|
||||
sinit = NULL;
|
||||
#endif
|
||||
isdeprecated = false;
|
||||
isdone = 0;
|
||||
#if IN_DMD
|
||||
objFileDone = 0;
|
||||
#endif
|
||||
protection = PROTundefined;
|
||||
parent = NULL;
|
||||
added = false;
|
||||
}
|
||||
|
||||
Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
|
||||
@@ -70,80 +68,60 @@ Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void EnumDeclaration::setScope(Scope *sc)
|
||||
{
|
||||
if (isdone)
|
||||
if (semanticRun > PASSinit)
|
||||
return;
|
||||
ScopeDsymbol::setScope(sc);
|
||||
}
|
||||
|
||||
int EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
if (!isAnonymous())
|
||||
return ScopeDsymbol::addMember(sc, sd, memnum);
|
||||
#if 0
|
||||
printf("EnumDeclaration::addMember() %s\n", toChars());
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
printf(" member %s\n", em->toChars());
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Anonymous enum members get added to enclosing scope.
|
||||
*/
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
ScopeDsymbol *scopesym = isAnonymous() ? sd : this;
|
||||
|
||||
if (!isAnonymous())
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
em->ed = this;
|
||||
//printf("add %s\n", em->toChars());
|
||||
em->addMember(sc, sd, 1);
|
||||
ScopeDsymbol::addMember(sc, sd, memnum);
|
||||
|
||||
if (!symtab)
|
||||
symtab = new DsymbolTable();
|
||||
}
|
||||
|
||||
if (members)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
em->ed = this;
|
||||
//printf("add %s to scope %s\n", em->toChars(), scopesym->toChars());
|
||||
em->addMember(sc, scopesym, 1);
|
||||
}
|
||||
}
|
||||
added = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EnumDeclaration::semantic0(Scope *sc)
|
||||
{
|
||||
/* This function is a hack to get around a significant problem.
|
||||
* The members of anonymous enums, like:
|
||||
* enum { A, B, C }
|
||||
* don't get installed into the symbol table until after they are
|
||||
* semantically analyzed, yet they're supposed to go into the enclosing
|
||||
* scope's table. Hence, when forward referenced, they come out as
|
||||
* 'undefined'. The real fix is to add them in at addSymbol() time.
|
||||
* But to get code to compile, we'll just do this quick hack at the moment
|
||||
* to compile it if it doesn't depend on anything else.
|
||||
*/
|
||||
|
||||
if (isdone || !scope)
|
||||
return;
|
||||
|
||||
parent = scope->parent;
|
||||
protection = scope->protection;
|
||||
|
||||
if (!isAnonymous() || memtype)
|
||||
return;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
if (em && (em->type || em->value))
|
||||
return;
|
||||
}
|
||||
|
||||
// Can do it
|
||||
semantic(sc);
|
||||
}
|
||||
|
||||
void EnumDeclaration::semantic(Scope *sc)
|
||||
{
|
||||
Type *t;
|
||||
Scope *sce;
|
||||
|
||||
//printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
|
||||
//printf("EnumDeclaration::semantic() %s\n", toChars());
|
||||
//printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
|
||||
if (!members && !memtype) // enum ident;
|
||||
return;
|
||||
|
||||
if (!memtype && !isAnonymous())
|
||||
{ // Set memtype if we can to reduce fwd reference errors
|
||||
memtype = Type::tint32; // case 1) enum ident { ... }
|
||||
}
|
||||
if (semanticRun > PASSinit)
|
||||
return; // semantic() already completed
|
||||
|
||||
if (symtab) // if already done
|
||||
{ if (isdone || !scope)
|
||||
return; // semantic() already completed
|
||||
}
|
||||
else
|
||||
if (!symtab)
|
||||
symtab = new DsymbolTable();
|
||||
|
||||
Scope *scx = NULL;
|
||||
@@ -167,8 +145,12 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
* 2. enum : memtype { ... }
|
||||
* 3. enum ident { ... }
|
||||
* 4. enum ident : memtype { ... }
|
||||
* 5. enum ident : memtype;
|
||||
* 6. enum ident;
|
||||
*/
|
||||
|
||||
type = type->semantic(loc, sc);
|
||||
|
||||
if (memtype)
|
||||
{
|
||||
memtype = memtype->semantic(loc, sc);
|
||||
@@ -192,207 +174,238 @@ void EnumDeclaration::semantic(Scope *sc)
|
||||
error("base type must not be void");
|
||||
memtype = Type::terror;
|
||||
}
|
||||
#if 0 // Decided to abandon this restriction for D 2.0
|
||||
if (!memtype->isintegral())
|
||||
{ error("base type must be of integral type, not %s", memtype->toChars());
|
||||
memtype = Type::tint32;
|
||||
if (memtype->ty == Terror)
|
||||
{
|
||||
errors = true;
|
||||
if (members)
|
||||
{
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->errors = true; // poison all the members
|
||||
}
|
||||
}
|
||||
semanticRun = PASSsemanticdone;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
isdone = 1;
|
||||
semanticRun = PASSsemanticdone;
|
||||
|
||||
if (!members) // enum ident : memtype;
|
||||
return;
|
||||
|
||||
if (members->dim == 0)
|
||||
{
|
||||
error("enum %s must have at least one member", toChars());
|
||||
errors = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Module::dprogress++;
|
||||
|
||||
type = type->semantic(loc, sc);
|
||||
Scope *sce;
|
||||
if (isAnonymous())
|
||||
sce = sc;
|
||||
else
|
||||
{ sce = sc->push(this);
|
||||
sce->parent = this;
|
||||
}
|
||||
if (members->dim == 0)
|
||||
error("enum %s must have at least one member", toChars());
|
||||
sce = sce->startCTFE();
|
||||
sce->setNoFree(); // needed for getMaxMinValue()
|
||||
|
||||
ScopeDsymbol *scopesym;
|
||||
if (isAnonymous())
|
||||
{
|
||||
/* Anonymous enum members get added to enclosing scope.
|
||||
*/
|
||||
for (Scope *sct = sce; sct; sct = sct->enclosing)
|
||||
{
|
||||
if (sct->scopesym)
|
||||
{
|
||||
scopesym = sct->scopesym;
|
||||
if (!sct->scopesym->symtab)
|
||||
sct->scopesym->symtab = new DsymbolTable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
scopesym = this;
|
||||
|
||||
int first = 1;
|
||||
Expression *elast = NULL;
|
||||
/* Each enum member gets the sce scope
|
||||
*/
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
Expression *e;
|
||||
Expression *emax = NULL;
|
||||
if (em)
|
||||
em->scope = sce;
|
||||
}
|
||||
|
||||
if (!em)
|
||||
/* The e->semantic(sce) can insert other symbols, such as
|
||||
* template instances and function literals.
|
||||
*/
|
||||
continue;
|
||||
|
||||
//printf(" Enum member '%s'\n",em->toChars());
|
||||
if (em->type)
|
||||
em->type = em->type->semantic(em->loc, sce);
|
||||
e = em->value;
|
||||
if (e)
|
||||
{
|
||||
assert(e->dyncast() == DYNCAST_EXPRESSION);
|
||||
e = e->ctfeSemantic(sce);
|
||||
e = e->ctfeInterpret();
|
||||
if (memtype)
|
||||
{
|
||||
e = e->implicitCastTo(sce, memtype);
|
||||
e = e->ctfeInterpret();
|
||||
if (!isAnonymous())
|
||||
e = e->castTo(sce, type);
|
||||
t = memtype;
|
||||
}
|
||||
else if (em->type)
|
||||
{
|
||||
e = e->implicitCastTo(sce, em->type);
|
||||
e = e->ctfeInterpret();
|
||||
assert(isAnonymous());
|
||||
t = e->type;
|
||||
}
|
||||
else
|
||||
t = e->type;
|
||||
}
|
||||
else if (first)
|
||||
{
|
||||
if (memtype)
|
||||
t = memtype;
|
||||
else if (em->type)
|
||||
t = em->type;
|
||||
else
|
||||
t = Type::tint32;
|
||||
e = new IntegerExp(em->loc, 0, Type::tint32);
|
||||
e = e->implicitCastTo(sce, t);
|
||||
e = e->ctfeInterpret();
|
||||
if (!isAnonymous())
|
||||
e = e->castTo(sce, type);
|
||||
}
|
||||
else if (memtype && memtype == Type::terror)
|
||||
{
|
||||
e = new ErrorExp();
|
||||
minval = e;
|
||||
maxval = e;
|
||||
defaultval = e;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lazily evaluate enum.max
|
||||
if (!emax)
|
||||
{
|
||||
emax = t->getProperty(Loc(), Id::max, 0);
|
||||
emax = emax->ctfeSemantic(sce);
|
||||
emax = emax->ctfeInterpret();
|
||||
}
|
||||
|
||||
// Set value to (elast + 1).
|
||||
// But first check that (elast != t.max)
|
||||
assert(elast);
|
||||
e = new EqualExp(TOKequal, em->loc, elast, emax);
|
||||
e = e->ctfeSemantic(sce);
|
||||
e = e->ctfeInterpret();
|
||||
if (e->toInteger())
|
||||
error("overflow of enum value %s", elast->toChars());
|
||||
|
||||
// Now set e to (elast + 1)
|
||||
e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
|
||||
e = e->ctfeSemantic(sce);
|
||||
e = e->castTo(sce, elast->type);
|
||||
e = e->ctfeInterpret();
|
||||
|
||||
if (t->isfloating())
|
||||
{
|
||||
// Check that e != elast (not always true for floats)
|
||||
Expression *etest = new EqualExp(TOKequal, em->loc, e, elast);
|
||||
etest = etest->ctfeSemantic(sce);
|
||||
etest = etest->ctfeInterpret();
|
||||
if (etest->toInteger())
|
||||
error("enum member %s has inexact value, due to loss of precision", em->toChars());
|
||||
}
|
||||
}
|
||||
elast = e;
|
||||
em->value = e;
|
||||
|
||||
// Add to symbol table only after evaluating 'value'
|
||||
if (isAnonymous() && !sc->func)
|
||||
{
|
||||
// already inserted to enclosing scope in addMember
|
||||
assert(em->ed);
|
||||
}
|
||||
else
|
||||
{
|
||||
em->ed = this;
|
||||
em->addMember(sc, scopesym, 1);
|
||||
}
|
||||
|
||||
/* Compute .min, .max and .default values.
|
||||
* If enum doesn't have a name, we can never identify the enum type,
|
||||
* so there is no purpose for a .min, .max or .default
|
||||
if (!added)
|
||||
{
|
||||
/* addMember() is not called when the EnumDeclaration appears as a function statement,
|
||||
* so we have to do what addMember() does and install the enum members in the right symbol
|
||||
* table
|
||||
*/
|
||||
if (!isAnonymous() && memtype != Type::terror)
|
||||
ScopeDsymbol *scopesym = NULL;
|
||||
if (isAnonymous())
|
||||
{
|
||||
if (first)
|
||||
{ defaultval = e;
|
||||
minval = e;
|
||||
maxval = e;
|
||||
}
|
||||
else
|
||||
{ Expression *ec;
|
||||
|
||||
/* In order to work successfully with UDTs,
|
||||
* build expressions to do the comparisons,
|
||||
* and let the semantic analyzer and constant
|
||||
* folder give us the result.
|
||||
*/
|
||||
|
||||
// Compute if(e < minval)
|
||||
ec = new CmpExp(TOKlt, em->loc, e, minval);
|
||||
ec = ec->ctfeSemantic(sce);
|
||||
ec = ec->ctfeInterpret();
|
||||
if (ec->toInteger())
|
||||
minval = e;
|
||||
|
||||
ec = new CmpExp(TOKgt, em->loc, e, maxval);
|
||||
ec = ec->ctfeSemantic(sce);
|
||||
ec = ec->ctfeInterpret();
|
||||
if (ec->toInteger())
|
||||
maxval = e;
|
||||
/* Anonymous enum members get added to enclosing scope.
|
||||
*/
|
||||
for (Scope *sct = sce; 1; sct = sct->enclosing)
|
||||
{
|
||||
assert(sct);
|
||||
if (sct->scopesym)
|
||||
{
|
||||
scopesym = sct->scopesym;
|
||||
if (!sct->scopesym->symtab)
|
||||
sct->scopesym->symtab = new DsymbolTable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
first = 0;
|
||||
else
|
||||
// Otherwise enum members are in the EnumDeclaration's symbol table
|
||||
scopesym = this;
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
if (em)
|
||||
{
|
||||
em->ed = this;
|
||||
em->addMember(sc, scopesym, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
if (em)
|
||||
em->semantic(em->scope);
|
||||
}
|
||||
//printf("defaultval = %lld\n", defaultval);
|
||||
|
||||
//if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
|
||||
if (sc != sce)
|
||||
sce->pop();
|
||||
//members->print();
|
||||
}
|
||||
|
||||
int EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
/******************************
|
||||
* Get the value of the .max/.min property as an Expression
|
||||
* Input:
|
||||
* id Id::max or Id::min
|
||||
*/
|
||||
|
||||
Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
|
||||
{
|
||||
//printf("EnumDeclaration::getMaxValue()\n");
|
||||
bool first = true;
|
||||
|
||||
Expression **pval = (id == Id::max) ? &maxval : &minval;
|
||||
|
||||
if (*pval)
|
||||
return *pval;
|
||||
|
||||
if (scope)
|
||||
semantic(scope);
|
||||
if (errors)
|
||||
goto Lerrors;
|
||||
if (semanticRun == PASSinit || !members)
|
||||
{
|
||||
error("is forward referenced looking for .%s", id->toChars());
|
||||
goto Lerrors;
|
||||
}
|
||||
if (!(memtype && memtype->isintegral()))
|
||||
{
|
||||
error(loc, "has no .%s property because base type %s is not an integral type",
|
||||
id->toChars(),
|
||||
memtype ? memtype->toChars() : "");
|
||||
goto Lerrors;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
if (!em)
|
||||
continue;
|
||||
if (em->errors)
|
||||
goto Lerrors;
|
||||
|
||||
Expression *e = em->value;
|
||||
if (first)
|
||||
{
|
||||
*pval = e;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In order to work successfully with UDTs,
|
||||
* build expressions to do the comparisons,
|
||||
* and let the semantic analyzer and constant
|
||||
* folder give us the result.
|
||||
*/
|
||||
|
||||
/* Compute:
|
||||
* if (e > maxval)
|
||||
* maxval = e;
|
||||
*/
|
||||
Expression *ec = new CmpExp(id == Id::max ? TOKgt : TOKlt, em->loc, e, *pval);
|
||||
ec = ec->semantic(em->scope);
|
||||
ec = ec->ctfeInterpret();
|
||||
if (ec->toInteger())
|
||||
*pval = e;
|
||||
}
|
||||
}
|
||||
return *pval;
|
||||
|
||||
Lerrors:
|
||||
*pval = new ErrorExp();
|
||||
return *pval;
|
||||
}
|
||||
|
||||
Expression *EnumDeclaration::getDefaultValue(Loc loc)
|
||||
{
|
||||
//printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
|
||||
if (defaultval)
|
||||
return defaultval;
|
||||
|
||||
if (scope)
|
||||
semantic(scope);
|
||||
if (errors)
|
||||
goto Lerrors;
|
||||
if (semanticRun == PASSinit || !members)
|
||||
{
|
||||
error(loc, "forward reference of %s.init", toChars());
|
||||
goto Lerrors;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*members)[i]->isEnumMember();
|
||||
if (!em)
|
||||
continue;
|
||||
defaultval = em->value;
|
||||
return defaultval;
|
||||
}
|
||||
|
||||
Lerrors:
|
||||
defaultval = new ErrorExp();
|
||||
return defaultval;
|
||||
}
|
||||
|
||||
Type *EnumDeclaration::getMemtype(Loc loc)
|
||||
{
|
||||
if (loc.linnum == 0)
|
||||
loc = this->loc;
|
||||
if (scope)
|
||||
{ /* Enum is forward referenced. We don't need to resolve the whole thing,
|
||||
* just the base type
|
||||
*/
|
||||
if (memtype)
|
||||
memtype = memtype->semantic(loc, scope);
|
||||
else
|
||||
{
|
||||
if (!isAnonymous())
|
||||
memtype = Type::tint32;
|
||||
}
|
||||
}
|
||||
if (!memtype)
|
||||
{
|
||||
if (!isAnonymous())
|
||||
memtype = Type::tint32;
|
||||
else
|
||||
{
|
||||
error(loc, "is forward referenced looking for base type");
|
||||
return Type::terror;
|
||||
}
|
||||
}
|
||||
return memtype;
|
||||
}
|
||||
|
||||
bool EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
if (isAnonymous())
|
||||
return Dsymbol::oneMembers(members, ps, ident);
|
||||
@@ -450,6 +463,11 @@ bool EnumDeclaration::isDeprecated()
|
||||
return isdeprecated;
|
||||
}
|
||||
|
||||
PROT EnumDeclaration::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
|
||||
Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
//printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
|
||||
@@ -521,24 +539,170 @@ const char *EnumMember::kind()
|
||||
|
||||
void EnumMember::semantic(Scope *sc)
|
||||
{
|
||||
//printf("EnumMember::semantic() %s\n", toChars());
|
||||
if (errors || semanticRun >= PASSsemanticdone)
|
||||
return;
|
||||
if (semanticRun == PASSsemantic)
|
||||
{
|
||||
error("circular reference to enum member");
|
||||
Lerrors:
|
||||
errors = true;
|
||||
semanticRun = PASSsemanticdone;
|
||||
return;
|
||||
}
|
||||
assert(ed);
|
||||
if (this->vd) return;
|
||||
ed->semantic(sc);
|
||||
assert(value);
|
||||
vd = new VarDeclaration(loc, type, ident, new ExpInitializer(loc, value->copy()));
|
||||
if (ed->errors)
|
||||
goto Lerrors;
|
||||
|
||||
vd->storage_class = STCmanifest;
|
||||
vd->semantic(sc);
|
||||
if (errors || semanticRun >= PASSsemanticdone)
|
||||
return;
|
||||
|
||||
vd->protection = ed->isAnonymous() ? ed->protection : PROTpublic;
|
||||
vd->parent = ed->isAnonymous() ? ed->parent : ed;
|
||||
vd->userAttributes = ed->isAnonymous() ? ed->userAttributes : NULL;
|
||||
semanticRun = PASSsemantic;
|
||||
if (scope)
|
||||
sc = scope;
|
||||
|
||||
// The first enum member is special
|
||||
bool first = (this == (*ed->members)[0]);
|
||||
|
||||
if (type)
|
||||
{
|
||||
type = type->semantic(loc, sc);
|
||||
assert(value); // "type id;" is not a valid enum member declaration
|
||||
}
|
||||
|
||||
if (value)
|
||||
{
|
||||
Expression *e = value;
|
||||
assert(e->dyncast() == DYNCAST_EXPRESSION);
|
||||
e = e->semantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
e = e->ctfeInterpret();
|
||||
if (first && !ed->memtype && !ed->isAnonymous())
|
||||
{
|
||||
ed->memtype = e->type;
|
||||
if (ed->memtype->ty == Terror)
|
||||
{
|
||||
ed->errors = true;
|
||||
goto Lerrors;
|
||||
}
|
||||
}
|
||||
|
||||
if (ed->memtype && !type)
|
||||
{
|
||||
e = e->implicitCastTo(sc, ed->memtype);
|
||||
e = e->ctfeInterpret();
|
||||
if (!ed->isAnonymous())
|
||||
e = e->castTo(sc, ed->type);
|
||||
}
|
||||
else if (type)
|
||||
{
|
||||
e = e->implicitCastTo(sc, type);
|
||||
e = e->ctfeInterpret();
|
||||
assert(ed->isAnonymous());
|
||||
}
|
||||
value = e;
|
||||
}
|
||||
else if (first)
|
||||
{
|
||||
Type *t;
|
||||
if (ed->memtype)
|
||||
t = ed->memtype;
|
||||
else
|
||||
{
|
||||
t = Type::tint32;
|
||||
if (!ed->isAnonymous())
|
||||
ed->memtype = t;
|
||||
}
|
||||
Expression *e = new IntegerExp(loc, 0, Type::tint32);
|
||||
e = e->implicitCastTo(sc, t);
|
||||
e = e->ctfeInterpret();
|
||||
if (!ed->isAnonymous())
|
||||
e = e->castTo(sc, ed->type);
|
||||
value = e;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Find the previous enum member,
|
||||
* and set this to be the previous value + 1
|
||||
*/
|
||||
EnumMember *emprev = NULL;
|
||||
for (size_t i = 0; i < ed->members->dim; i++)
|
||||
{
|
||||
EnumMember *em = (*ed->members)[i]->isEnumMember();
|
||||
if (em)
|
||||
{
|
||||
if (em == this)
|
||||
break;
|
||||
emprev = em;
|
||||
}
|
||||
}
|
||||
assert(emprev);
|
||||
if (emprev->semanticRun < PASSsemanticdone) // if forward reference
|
||||
emprev->semantic(emprev->scope); // resolve it
|
||||
if (emprev->errors)
|
||||
goto Lerrors;
|
||||
|
||||
Expression *eprev = emprev->value;
|
||||
Type *tprev = eprev->type->equals(ed->type) ? ed->memtype : eprev->type;
|
||||
|
||||
Expression *emax = tprev->getProperty(Loc(), Id::max, 0);
|
||||
emax = emax->semantic(sc);
|
||||
emax = emax->ctfeInterpret();
|
||||
|
||||
// Set value to (eprev + 1).
|
||||
// But first check that (eprev != emax)
|
||||
assert(eprev);
|
||||
Expression *e = new EqualExp(TOKequal, loc, eprev, emax);
|
||||
e = e->semantic(sc);
|
||||
e = e->ctfeInterpret();
|
||||
if (e->toInteger())
|
||||
{
|
||||
error("initialization with (%s.%s + 1) causes overflow for type '%s'", emprev->ed->toChars(), emprev->toChars(), ed->type->toBasetype()->toChars());
|
||||
goto Lerrors;
|
||||
}
|
||||
|
||||
// Now set e to (eprev + 1)
|
||||
e = new AddExp(loc, eprev, new IntegerExp(loc, 1, Type::tint32));
|
||||
e = e->semantic(sc);
|
||||
e = e->castTo(sc, eprev->type);
|
||||
e = e->ctfeInterpret();
|
||||
|
||||
if (e->type->isfloating())
|
||||
{
|
||||
// Check that e != eprev (not always true for floats)
|
||||
Expression *etest = new EqualExp(TOKequal, loc, e, eprev);
|
||||
etest = etest->semantic(sc);
|
||||
etest = etest->ctfeInterpret();
|
||||
if (etest->toInteger())
|
||||
{
|
||||
error("has inexact value, due to loss of precision");
|
||||
goto Lerrors;
|
||||
}
|
||||
}
|
||||
value = e;
|
||||
}
|
||||
|
||||
semanticRun = PASSsemanticdone;
|
||||
}
|
||||
|
||||
Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
|
||||
{
|
||||
semantic(sc);
|
||||
assert(vd);
|
||||
if (errors)
|
||||
return new ErrorExp();
|
||||
if (!vd)
|
||||
{
|
||||
assert(value);
|
||||
vd = new VarDeclaration(loc, type, ident, new ExpInitializer(loc, value->copy()));
|
||||
|
||||
vd->storage_class = STCmanifest;
|
||||
vd->semantic(sc);
|
||||
|
||||
vd->protection = ed->isAnonymous() ? ed->protection : PROTpublic;
|
||||
vd->parent = ed->isAnonymous() ? ed->parent : ed;
|
||||
vd->userAttributes = ed->isAnonymous() ? ed->userAttributes : NULL;
|
||||
}
|
||||
Expression *e = new VarExp(loc, vd);
|
||||
return e->semantic(sc);
|
||||
}
|
||||
|
||||
+34
-21
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2008 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -18,39 +18,42 @@
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
struct Expression;
|
||||
class Identifier;
|
||||
class Type;
|
||||
class Expression;
|
||||
struct HdrGenState;
|
||||
struct VarDeclaration;
|
||||
class VarDeclaration;
|
||||
|
||||
struct EnumDeclaration : ScopeDsymbol
|
||||
{ /* enum ident : memtype { ... }
|
||||
class EnumDeclaration : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
/* The separate, and distinct, cases are:
|
||||
* 1. enum { ... }
|
||||
* 2. enum : memtype { ... }
|
||||
* 3. enum id { ... }
|
||||
* 4. enum id : memtype { ... }
|
||||
* 5. enum id : memtype;
|
||||
* 6. enum id;
|
||||
*/
|
||||
Type *type; // the TypeEnum
|
||||
Type *memtype; // type of the members
|
||||
enum PROT protection;
|
||||
PROT protection;
|
||||
|
||||
#if DMDV1
|
||||
dinteger_t maxval;
|
||||
dinteger_t minval;
|
||||
dinteger_t defaultval; // default initializer
|
||||
#else
|
||||
private:
|
||||
Expression *maxval;
|
||||
Expression *minval;
|
||||
Expression *defaultval; // default initializer
|
||||
#endif
|
||||
|
||||
public:
|
||||
bool isdeprecated;
|
||||
int isdone; // 0: not done
|
||||
// 1: semantic() successfully completed
|
||||
bool added;
|
||||
|
||||
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
|
||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||
int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
|
||||
void setScope(Scope *sc);
|
||||
void semantic0(Scope *sc);
|
||||
void semantic(Scope *sc);
|
||||
int oneMember(Dsymbol **ps, Identifier *ident = NULL);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Type *getType();
|
||||
const char *kind();
|
||||
@@ -58,6 +61,10 @@ struct EnumDeclaration : ScopeDsymbol
|
||||
Dsymbol *search(Loc, Identifier *ident, int flags);
|
||||
#endif
|
||||
bool isDeprecated(); // is Dsymbol deprecated?
|
||||
PROT prot();
|
||||
Expression *getMaxMinValue(Loc loc, Identifier *id);
|
||||
Expression *getDefaultValue(Loc loc);
|
||||
Type *getMemtype(Loc loc);
|
||||
|
||||
void emitComment(Scope *sc);
|
||||
void toJson(JsonOut *json);
|
||||
@@ -66,7 +73,6 @@ struct EnumDeclaration : ScopeDsymbol
|
||||
EnumDeclaration *isEnumDeclaration() { return this; }
|
||||
|
||||
#if IN_DMD
|
||||
bool objFileDone; // if toObjFile was already called
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
void toDebug();
|
||||
int cvMember(unsigned char *p);
|
||||
@@ -81,11 +87,18 @@ struct EnumDeclaration : ScopeDsymbol
|
||||
};
|
||||
|
||||
|
||||
struct EnumMember : Dsymbol
|
||||
class EnumMember : public Dsymbol
|
||||
{
|
||||
EnumDeclaration *ed;
|
||||
public:
|
||||
/* Can take the following forms:
|
||||
* 1. id
|
||||
* 2. id = value
|
||||
* 3. type id = value
|
||||
*/
|
||||
Expression *value;
|
||||
Type *type;
|
||||
|
||||
EnumDeclaration *ed;
|
||||
VarDeclaration *vd;
|
||||
|
||||
EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
|
||||
|
||||
+1720
-975
File diff suppressed because it is too large
Load Diff
+295
-197
File diff suppressed because it is too large
Load Diff
+599
-615
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -30,12 +30,12 @@ hash_t Identifier::hashCode()
|
||||
return String::calcHash(string);
|
||||
}
|
||||
|
||||
int Identifier::equals(Object *o)
|
||||
bool Identifier::equals(RootObject *o)
|
||||
{
|
||||
return this == o || memcmp(string,o->toChars(),len+1) == 0;
|
||||
}
|
||||
|
||||
int Identifier::compare(Object *o)
|
||||
int Identifier::compare(RootObject *o)
|
||||
{
|
||||
return memcmp(string, o->toChars(), len + 1);
|
||||
}
|
||||
|
||||
+4
-10
@@ -17,23 +17,17 @@
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#if IN_LLVM
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct Identifier : Object
|
||||
class Identifier : public RootObject
|
||||
{
|
||||
public:
|
||||
int value;
|
||||
const char *string;
|
||||
size_t len;
|
||||
|
||||
Identifier(const char *string, int value);
|
||||
int equals(Object *o);
|
||||
bool equals(RootObject *o);
|
||||
hash_t hashCode();
|
||||
int compare(Object *o);
|
||||
int compare(RootObject *o);
|
||||
void print();
|
||||
char *toChars();
|
||||
const char *toHChars2();
|
||||
|
||||
+6
-2
@@ -266,7 +266,7 @@ Msgtable msgtable[] =
|
||||
{ "lib" },
|
||||
{ "msg" },
|
||||
{ "startaddress" },
|
||||
{ "mangle" },
|
||||
{ "mangle" },
|
||||
|
||||
#if IN_LLVM
|
||||
// LDC-specific pragmas.
|
||||
@@ -324,6 +324,7 @@ Msgtable msgtable[] =
|
||||
{ "WinMain" },
|
||||
{ "DllMain" },
|
||||
{ "tls_get_addr", "___tls_get_addr" },
|
||||
{ "entrypoint", "__entrypoint" },
|
||||
|
||||
// varargs implementation
|
||||
{ "va_argsave_t", "__va_argsave_t" },
|
||||
@@ -385,6 +386,9 @@ Msgtable msgtable[] =
|
||||
{ "compiles" },
|
||||
{ "parameters" },
|
||||
{ "getAttributes" },
|
||||
{ "getUnitTests" },
|
||||
{ "isOverrideFunction" },
|
||||
{ "getVirtualIndex" }
|
||||
};
|
||||
|
||||
|
||||
@@ -406,7 +410,7 @@ int main()
|
||||
#endif
|
||||
fprintf(fp, "#ifndef DMD_ID_H\n");
|
||||
fprintf(fp, "#define DMD_ID_H 1\n");
|
||||
fprintf(fp, "struct Identifier;\n");
|
||||
fprintf(fp, "class Identifier;\n");
|
||||
fprintf(fp, "struct Id\n");
|
||||
fprintf(fp, "{\n");
|
||||
|
||||
|
||||
+56
-33
@@ -30,6 +30,18 @@ Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *alias
|
||||
: Dsymbol(NULL)
|
||||
{
|
||||
assert(id);
|
||||
#if 0
|
||||
printf("Import::Import(");
|
||||
if (packages && packages->dim)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{
|
||||
Identifier *id = (*packages)[i];
|
||||
printf("%s.", id->toChars());
|
||||
}
|
||||
}
|
||||
printf("%s)\n", id->toChars());
|
||||
#endif
|
||||
this->loc = loc;
|
||||
this->packages = packages;
|
||||
this->id = id;
|
||||
@@ -68,7 +80,7 @@ const char *Import::kind()
|
||||
return isstatic ? (char *)"static import" : (char *)"import";
|
||||
}
|
||||
|
||||
enum PROT Import::prot()
|
||||
PROT Import::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
@@ -89,10 +101,11 @@ Dsymbol *Import::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void Import::load(Scope *sc)
|
||||
{
|
||||
//printf("Import::load('%s')\n", toChars());
|
||||
//printf("Import::load('%s') %p\n", toPrettyChars(), this);
|
||||
|
||||
// See if existing module
|
||||
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
|
||||
#if 0
|
||||
if (pkg && pkg->isModule())
|
||||
{
|
||||
::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?",
|
||||
@@ -100,6 +113,7 @@ void Import::load(Scope *sc)
|
||||
mod = pkg->isModule(); // Error recovery - treat as import of that module
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Dsymbol *s = dst->lookup(id);
|
||||
if (s)
|
||||
{
|
||||
@@ -107,7 +121,31 @@ void Import::load(Scope *sc)
|
||||
mod = (Module *)s;
|
||||
else
|
||||
{
|
||||
if (pkg)
|
||||
if (s->isAliasDeclaration())
|
||||
{
|
||||
::error(loc, "%s %s conflicts with %s", s->kind(), s->toPrettyChars(), id->toChars());
|
||||
}
|
||||
else if (Package *p = s->isPackage())
|
||||
{
|
||||
if (p->isPkgMod == PKGunknown)
|
||||
{
|
||||
mod = Module::load(loc, packages, id);
|
||||
if (!mod)
|
||||
p->isPkgMod = PKGpackage;
|
||||
else
|
||||
assert(p->isPkgMod == PKGmodule);
|
||||
}
|
||||
else if (p->isPkgMod == PKGmodule)
|
||||
{
|
||||
mod = p->mod;
|
||||
}
|
||||
if (p->isPkgMod != PKGmodule)
|
||||
{
|
||||
::error(loc, "can only import from a module, not from package %s.%s",
|
||||
p->toPrettyChars(), id->toChars());
|
||||
}
|
||||
}
|
||||
else if (pkg)
|
||||
{
|
||||
::error(loc, "can only import from a module, not from package %s.%s",
|
||||
pkg->toPrettyChars(), id->toChars());
|
||||
@@ -128,36 +166,16 @@ void Import::load(Scope *sc)
|
||||
{
|
||||
dst->insert(id, mod); // id may be different from mod->ident,
|
||||
// if so then insert alias
|
||||
if (!mod->importedFrom)
|
||||
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
|
||||
}
|
||||
}
|
||||
if (mod && !mod->importedFrom)
|
||||
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
|
||||
if (!pkg)
|
||||
pkg = mod;
|
||||
|
||||
//printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
|
||||
}
|
||||
|
||||
void escapePath(OutBuffer *buf, const char *fname)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
switch (*fname)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case '(':
|
||||
case ')':
|
||||
case '\\':
|
||||
buf->writebyte('\\');
|
||||
default:
|
||||
buf->writebyte(*fname);
|
||||
break;
|
||||
}
|
||||
fname++;
|
||||
}
|
||||
}
|
||||
|
||||
void Import::importAll(Scope *sc)
|
||||
{
|
||||
if (!mod)
|
||||
@@ -178,7 +196,7 @@ void Import::importAll(Scope *sc)
|
||||
|
||||
void Import::semantic(Scope *sc)
|
||||
{
|
||||
//printf("Import::semantic('%s')\n", toChars());
|
||||
//printf("Import::semantic('%s')\n", toPrettyChars());
|
||||
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
@@ -260,7 +278,10 @@ void Import::semantic(Scope *sc)
|
||||
|
||||
if (global.params.moduleDeps != NULL &&
|
||||
// object self-imports itself, so skip that (Bugzilla 7547)
|
||||
!(id == Id::object && sc->module->ident == Id::object))
|
||||
!(id == Id::object && sc->module->ident == Id::object) &&
|
||||
// don't list pseudo modules __entrypoint.d, __main.d (Bugzilla 11117, 11164)
|
||||
sc->module->ident != Id::entrypoint &&
|
||||
strcmp(sc->module->ident->string, "__main") != 0)
|
||||
{
|
||||
/* The grammar of the file is:
|
||||
* ImportDeclaration
|
||||
@@ -276,10 +297,12 @@ void Import::semantic(Scope *sc)
|
||||
*/
|
||||
|
||||
OutBuffer *ob = global.params.moduleDeps;
|
||||
|
||||
ob->writestring(sc->module->toPrettyChars());
|
||||
Module* imod = sc->instantiatingModule ? sc->instantiatingModule : sc->module;
|
||||
if (!global.params.moduleDepsFile)
|
||||
ob->writestring("depsImport ");
|
||||
ob->writestring(imod->toPrettyChars());
|
||||
ob->writestring(" (");
|
||||
escapePath(ob, sc->module->srcfile->toChars());
|
||||
escapePath(ob, imod->srcfile->toChars());
|
||||
ob->writestring(") : ");
|
||||
|
||||
// use protection instead of sc->protection because it couldn't be
|
||||
@@ -403,7 +426,7 @@ Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
|
||||
return pkg->search(loc, ident, flags);
|
||||
}
|
||||
|
||||
int Import::overloadInsert(Dsymbol *s)
|
||||
bool Import::overloadInsert(Dsymbol *s)
|
||||
{
|
||||
/* Allow multiple imports with the same package base, but disallow
|
||||
* alias collisions (Bugzilla 5412).
|
||||
@@ -411,9 +434,9 @@ int Import::overloadInsert(Dsymbol *s)
|
||||
assert(ident && ident == s->ident);
|
||||
Import *imp;
|
||||
if (!aliasId && (imp = s->isImport()) != NULL && !imp->aliasId)
|
||||
return TRUE;
|
||||
return true;
|
||||
else
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
|
||||
+18
-14
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -18,37 +18,41 @@
|
||||
#include "dsymbol.h"
|
||||
|
||||
|
||||
struct Identifier;
|
||||
class Identifier;
|
||||
struct Scope;
|
||||
struct OutBuffer;
|
||||
struct Module;
|
||||
struct Package;
|
||||
struct AliasDeclaration;
|
||||
class Module;
|
||||
class Package;
|
||||
class AliasDeclaration;
|
||||
struct HdrGenState;
|
||||
|
||||
struct Import : Dsymbol
|
||||
class Import : public Dsymbol
|
||||
{
|
||||
public:
|
||||
/* static import aliasId = pkg1.pkg2.id : alias1 = name1, alias2 = name2;
|
||||
*/
|
||||
|
||||
Identifiers *packages; // array of Identifier's representing packages
|
||||
Identifier *id; // module Identifier
|
||||
Identifier *aliasId;
|
||||
int isstatic; // !=0 if static import
|
||||
enum PROT protection;
|
||||
PROT protection;
|
||||
|
||||
// Pairs of alias=name to bind into current namespace
|
||||
Identifiers names;
|
||||
Identifiers aliases;
|
||||
|
||||
AliasDeclarations aliasdecls; // AliasDeclarations for names/aliases
|
||||
|
||||
Module *mod;
|
||||
Package *pkg; // leftmost package/module
|
||||
|
||||
Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
|
||||
int isstatic);
|
||||
void addAlias(Identifier *name, Identifier *alias);
|
||||
|
||||
AliasDeclarations aliasdecls; // corresponding AliasDeclarations for alias=name pairs
|
||||
|
||||
Module *mod;
|
||||
Package *pkg; // leftmost package/module
|
||||
|
||||
const char *kind();
|
||||
enum PROT prot();
|
||||
PROT prot();
|
||||
Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||
void load(Scope *sc);
|
||||
void importAll(Scope *sc);
|
||||
@@ -57,7 +61,7 @@ struct Import : Dsymbol
|
||||
Dsymbol *toAlias();
|
||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
bool overloadInsert(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void toJson(JsonOut *json);
|
||||
|
||||
|
||||
+184
-220
@@ -68,10 +68,10 @@ char *Initializer::toChars()
|
||||
{
|
||||
HdrGenState hgs;
|
||||
|
||||
memset(&hgs, 0, sizeof(hgs));
|
||||
OutBuffer *buf = new OutBuffer();
|
||||
toCBuffer(buf, &hgs);
|
||||
return buf->toChars();
|
||||
OutBuffer buf;
|
||||
toCBuffer(&buf, &hgs);
|
||||
buf.writebyte(0);
|
||||
return buf.extractData();
|
||||
}
|
||||
|
||||
/********************************** ErrorInitializer ***************************/
|
||||
@@ -132,8 +132,7 @@ Initializer *VoidInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInt
|
||||
|
||||
Expression *VoidInitializer::toExpression(Type *t)
|
||||
{
|
||||
error(loc, "void initializer has no value");
|
||||
return new ErrorExp();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -148,10 +147,6 @@ void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
StructInitializer::StructInitializer(Loc loc)
|
||||
: Initializer(loc)
|
||||
{
|
||||
ad = NULL;
|
||||
#if IN_LLVM
|
||||
ltype = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
Initializer *StructInitializer::syntaxCopy()
|
||||
@@ -181,101 +176,30 @@ void StructInitializer::addInit(Identifier *field, Initializer *value)
|
||||
|
||||
Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
//printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
|
||||
vars.setDim(field.dim);
|
||||
t = t->toBasetype();
|
||||
if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct)
|
||||
t = t->nextOf()->toBasetype();
|
||||
if (t->ty == Tstruct)
|
||||
{
|
||||
size_t fieldi = 0;
|
||||
|
||||
TypeStruct *ts = (TypeStruct *)t;
|
||||
ad = ts->sym;
|
||||
if (ad->ctor)
|
||||
StructDeclaration *sd = ((TypeStruct *)t)->sym;
|
||||
if (sd->ctor)
|
||||
{
|
||||
error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
|
||||
ad->kind(), ad->toChars(), ad->toChars());
|
||||
StructDeclaration *sd = ad->isStructDeclaration();
|
||||
assert(sd);
|
||||
sd->size(loc);
|
||||
if (sd->sizeok != SIZEOKdone)
|
||||
{
|
||||
error(loc, "struct %s is forward referenced", sd->toChars());
|
||||
errors = 1;
|
||||
goto Lerror;
|
||||
sd->kind(), sd->toChars(), sd->toChars());
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
size_t nfields = sd->fields.dim - sd->isNested();
|
||||
for (size_t i = 0; i < field.dim; i++)
|
||||
{
|
||||
Identifier *id = field[i];
|
||||
Initializer *val = value[i];
|
||||
Dsymbol *s;
|
||||
VarDeclaration *v;
|
||||
|
||||
if (id == NULL)
|
||||
{
|
||||
if (fieldi >= nfields)
|
||||
{ error(loc, "too many initializers for %s", ad->toChars());
|
||||
errors = 1;
|
||||
field.remove(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = ad->fields[fieldi];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//s = ad->symtab->lookup(id);
|
||||
s = ad->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
s = ad->search_correct(id);
|
||||
if (s)
|
||||
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
|
||||
id->toChars(), t->toChars(), s->kind(), s->toChars());
|
||||
else
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||
errors = 1;
|
||||
continue;
|
||||
}
|
||||
s = s->toAlias();
|
||||
Expression *e = fill(sc, t, needInterpret);
|
||||
if (e->op == TOKerror)
|
||||
return new ErrorInitializer();
|
||||
|
||||
// Find out which field index it is
|
||||
for (fieldi = 0; 1; fieldi++)
|
||||
{
|
||||
if (fieldi >= nfields)
|
||||
{
|
||||
error(loc, "%s.%s is not a per-instance initializable field",
|
||||
t->toChars(), s->toChars());
|
||||
errors = 1;
|
||||
break;
|
||||
}
|
||||
if (s == ad->fields[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s && (v = s->isVarDeclaration()) != NULL)
|
||||
{
|
||||
val = val->semantic(sc, v->type->addMod(t->mod), needInterpret);
|
||||
value[i] = val;
|
||||
vars[i] = v;
|
||||
if (val->isErrorInitializer())
|
||||
errors = 1;
|
||||
}
|
||||
else
|
||||
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
|
||||
errors = 1;
|
||||
}
|
||||
fieldi++;
|
||||
}
|
||||
ExpInitializer *ie = new ExpInitializer(loc, e);
|
||||
return ie->semantic(sc, t, needInterpret);
|
||||
}
|
||||
else if (t->ty == Tdelegate && value.dim == 0)
|
||||
{ /* Rewrite as empty delegate literal { }
|
||||
{
|
||||
/* Rewrite as empty delegate literal { }
|
||||
*/
|
||||
Parameters *arguments = new Parameters;
|
||||
Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
|
||||
@@ -286,17 +210,9 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
|
||||
ExpInitializer *ie = new ExpInitializer(loc, e);
|
||||
return ie->semantic(sc, t, needInterpret);
|
||||
}
|
||||
else
|
||||
{
|
||||
error(loc, "a struct is not a valid initializer for a %s", t->toChars());
|
||||
errors = 1;
|
||||
}
|
||||
Lerror:
|
||||
if (errors)
|
||||
{
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
return this;
|
||||
|
||||
error(loc, "a struct is not a valid initializer for a %s", t->toChars());
|
||||
return new ErrorInitializer();
|
||||
}
|
||||
|
||||
/***************************************
|
||||
@@ -305,34 +221,42 @@ Lerror:
|
||||
* same thing.
|
||||
*/
|
||||
Expression *StructInitializer::toExpression(Type *t)
|
||||
{ Expression *e;
|
||||
size_t offset;
|
||||
{
|
||||
// cannot convert to an expression without target 'ad'
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//printf("StructInitializer::toExpression() %s\n", toChars());
|
||||
if (!ad) // if fwd referenced
|
||||
return NULL;
|
||||
StructDeclaration *sd = ad->isStructDeclaration();
|
||||
if (!sd)
|
||||
return NULL;
|
||||
Expression *StructInitializer::fill(Scope *sc, Type *t, NeedInterpret needInterpret)
|
||||
{
|
||||
//printf("StructInitializer::fill(sc = %p, '%s')\n", sc, toChars());
|
||||
assert(t->ty == Tstruct);
|
||||
StructDeclaration *sd = ((TypeStruct *)t)->sym;
|
||||
sd->size(loc);
|
||||
if (sd->sizeok != SIZEOKdone)
|
||||
return new ErrorExp();
|
||||
size_t nfields = sd->fields.dim - sd->isNested();
|
||||
|
||||
Expressions *elements = new Expressions();
|
||||
size_t nfields = ad->fields.dim - sd->isNested();
|
||||
elements->setDim(nfields);
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{
|
||||
(*elements)[i] = NULL;
|
||||
}
|
||||
size_t fieldi = 0;
|
||||
for (size_t i = 0; i < value.dim; i++)
|
||||
|
||||
// Run semantic for explicitly given initializers
|
||||
bool errors = false;
|
||||
for (size_t fieldi = 0, i = 0; i < field.dim; i++)
|
||||
{
|
||||
Identifier *id = field[i];
|
||||
if (id)
|
||||
if (Identifier *id = field[i])
|
||||
{
|
||||
Dsymbol * s = ad->search(loc, id, 0);
|
||||
Dsymbol *s = sd->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
|
||||
goto Lerror;
|
||||
s = sd->search_correct(id);
|
||||
if (s)
|
||||
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
|
||||
id->toChars(), sd->toChars(), s->kind(), s->toChars());
|
||||
else
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
s = s->toAlias();
|
||||
|
||||
@@ -341,126 +265,155 @@ Expression *StructInitializer::toExpression(Type *t)
|
||||
{
|
||||
if (fieldi >= nfields)
|
||||
{
|
||||
s->error("is not a per-instance initializable field");
|
||||
goto Lerror;
|
||||
error(loc, "%s.%s is not a per-instance initializable field",
|
||||
sd->toChars(), s->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (s == ad->fields[fieldi])
|
||||
if (s == sd->fields[fieldi])
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (fieldi >= nfields)
|
||||
{ error(loc, "too many initializers for '%s'", ad->toChars());
|
||||
goto Lerror;
|
||||
{
|
||||
error(loc, "too many initializers for %s", sd->toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
Initializer *iz = value[i];
|
||||
if (!iz)
|
||||
goto Lno;
|
||||
Expression *ex = iz->toExpression();
|
||||
if (!ex)
|
||||
goto Lno;
|
||||
|
||||
VarDeclaration *vd = sd->fields[fieldi];
|
||||
if ((*elements)[fieldi])
|
||||
{ error(loc, "duplicate initializer for field '%s'",
|
||||
ad->fields[fieldi]->toChars());
|
||||
goto Lerror;
|
||||
{
|
||||
error(loc, "duplicate initializer for field '%s'", vd->toChars());
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
for (size_t j = 0; j < nfields; j++)
|
||||
{
|
||||
VarDeclaration *v2 = sd->fields[j];
|
||||
bool overlap = (vd->offset < v2->offset + v2->type->size() &&
|
||||
v2->offset < vd->offset + vd->type->size());
|
||||
if (overlap && (*elements)[j])
|
||||
{
|
||||
error(loc, "overlapping initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sc);
|
||||
Initializer *iz = value[i];
|
||||
iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret);
|
||||
Expression *ex = iz->toExpression();
|
||||
if (ex->op == TOKerror)
|
||||
{
|
||||
errors = true;
|
||||
continue;
|
||||
}
|
||||
value[i] = iz;
|
||||
(*elements)[fieldi] = ex;
|
||||
++fieldi;
|
||||
}
|
||||
// Now, fill in any missing elements with default initializers.
|
||||
// We also need to validate any anonymous unions
|
||||
offset = 0;
|
||||
for (size_t i = 0; i < elements->dim; )
|
||||
{
|
||||
VarDeclaration * vd = ad->fields[i]->isVarDeclaration();
|
||||
if (errors)
|
||||
return new ErrorExp();
|
||||
|
||||
//printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset);
|
||||
if (vd->offset < offset)
|
||||
// Fill in missing any elements with default initializers
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{
|
||||
if ((*elements)[i])
|
||||
continue;
|
||||
VarDeclaration *vd = sd->fields[i];
|
||||
VarDeclaration *vx = vd;
|
||||
if (vd->init && vd->init->isVoidInitializer())
|
||||
vx = NULL;
|
||||
// Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
|
||||
size_t fieldi = i;
|
||||
for (size_t j = 0; j < nfields; j++)
|
||||
{
|
||||
// Only the first field of a union can have an initializer
|
||||
if ((*elements)[i])
|
||||
goto Lno;
|
||||
if (i == j)
|
||||
continue;
|
||||
VarDeclaration *v2 = sd->fields[j];
|
||||
if (v2->init && v2->init->isVoidInitializer())
|
||||
continue;
|
||||
|
||||
bool overlap = (vd->offset < v2->offset + v2->type->size() &&
|
||||
v2->offset < vd->offset + vd->type->size());
|
||||
if (!overlap)
|
||||
continue;
|
||||
|
||||
if ((*elements)[j])
|
||||
{
|
||||
vx = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* Prefer first found non-void-initialized field
|
||||
* union U { int a; int b = 2; }
|
||||
* U u; // Error: overlapping initialization for field a and b
|
||||
*/
|
||||
if (!vx)
|
||||
vx = v2, fieldi = j;
|
||||
else if (v2->init)
|
||||
{
|
||||
error(loc, "overlapping initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
}
|
||||
#else // fix Bugzilla 1432
|
||||
/* Prefer explicitly initialized field
|
||||
* union U { int a; int b = 2; }
|
||||
* U u; // OK (u.b == 2)
|
||||
*/
|
||||
if (!vx || !vx->init && v2->init)
|
||||
vx = v2, fieldi = j;
|
||||
else if (vx->init && v2->init)
|
||||
{
|
||||
error(loc, "overlapping default initialization for field %s and %s",
|
||||
v2->toChars(), vd->toChars());
|
||||
}
|
||||
else
|
||||
assert(vx->init || !vx->init && !v2->init);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
if (vx)
|
||||
{
|
||||
if (!(*elements)[i])
|
||||
{ // Default initialize
|
||||
if (vd->init)
|
||||
if (vx->init)
|
||||
{
|
||||
assert(!vx->init->isVoidInitializer());
|
||||
if (vx->scope)
|
||||
{
|
||||
if (vd->scope)
|
||||
{ // Do deferred semantic analysis
|
||||
Initializer *i2 = vd->init->syntaxCopy();
|
||||
i2 = i2->semantic(vd->scope, vd->type, INITinterpret);
|
||||
(*elements)[i] = i2->toExpression();
|
||||
if (!global.gag)
|
||||
{ vd->scope = NULL;
|
||||
vd->init = i2; // save result
|
||||
}
|
||||
// Do deferred semantic analysis
|
||||
Initializer *i2 = vx->init->syntaxCopy();
|
||||
i2 = i2->semantic(vx->scope, vx->type, INITinterpret);
|
||||
(*elements)[fieldi] = i2->toExpression();
|
||||
if (!global.gag)
|
||||
{
|
||||
vx->scope = NULL;
|
||||
vx->init = i2; // save result
|
||||
}
|
||||
else
|
||||
(*elements)[i] = vd->init->toExpression();
|
||||
}
|
||||
else
|
||||
(*elements)[i] = vd->type->defaultInit();
|
||||
(*elements)[fieldi] = vx->init->toExpression();
|
||||
}
|
||||
else
|
||||
(*elements)[fieldi] = vx->type->defaultInit();
|
||||
}
|
||||
offset = vd->offset + vd->type->size();
|
||||
i++;
|
||||
#if 0
|
||||
int unionSize = ad->numFieldsInUnion(i);
|
||||
if (unionSize == 1)
|
||||
{ // Not a union -- default initialize if missing
|
||||
if (!(*elements)[i])
|
||||
(*elements)[i] = vd->type->defaultInit();
|
||||
}
|
||||
else
|
||||
{ // anonymous union -- check for errors
|
||||
int found = -1; // index of the first field with an initializer
|
||||
for (size_t j = i; j < i + unionSize; ++j)
|
||||
{
|
||||
if (!(*elements)[j])
|
||||
continue;
|
||||
if (found >= 0)
|
||||
{
|
||||
VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration();
|
||||
VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration();
|
||||
error(loc, "%s cannot have initializers for fields %s and %s in same union",
|
||||
ad->toChars(),
|
||||
v1->toChars(), v->toChars());
|
||||
goto Lerror;
|
||||
}
|
||||
found = j;
|
||||
}
|
||||
if (found == -1)
|
||||
{
|
||||
error(loc, "no initializer for union that contains field %s",
|
||||
vd->toChars());
|
||||
goto Lerror;
|
||||
}
|
||||
}
|
||||
i += unionSize;
|
||||
#endif
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (*elements)[i];
|
||||
{
|
||||
Expression *e = (*elements)[i];
|
||||
if (e && e->op == TOKerror)
|
||||
return e;
|
||||
}
|
||||
|
||||
e = new StructLiteralExp(loc, sd, elements);
|
||||
e->type = sd->type;
|
||||
Expression *e = new StructLiteralExp(loc, sd, elements, t);
|
||||
if (sc)
|
||||
e = e->semantic(sc);
|
||||
else
|
||||
e->type = sd->type; // from glue layer
|
||||
return e;
|
||||
|
||||
Lno:
|
||||
delete elements;
|
||||
return NULL;
|
||||
|
||||
Lerror:
|
||||
delete elements;
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
|
||||
void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
//printf("StructInitializer::toCBuffer()\n");
|
||||
@@ -561,7 +514,10 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
|
||||
{
|
||||
Expression *idx = index[i];
|
||||
if (idx)
|
||||
{ idx = idx->ctfeSemantic(sc);
|
||||
{
|
||||
sc = sc->startCTFE();
|
||||
idx = idx->semantic(sc);
|
||||
sc = sc->endCTFE();
|
||||
idx = idx->ctfeInterpret();
|
||||
index[i] = idx;
|
||||
length = idx->toInteger();
|
||||
@@ -945,11 +901,10 @@ bool arrayHasNonConstPointers(Expressions *elems)
|
||||
Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
|
||||
{
|
||||
//printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
|
||||
if (needInterpret)
|
||||
exp = exp->ctfeSemantic(sc);
|
||||
else
|
||||
exp = exp->semantic(sc);
|
||||
if (needInterpret) sc = sc->startCTFE();
|
||||
exp = exp->semantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
if (needInterpret) sc = sc->endCTFE();
|
||||
if (exp->op == TOKerror)
|
||||
return this;
|
||||
|
||||
@@ -1066,17 +1021,17 @@ Type *ExpInitializer::inferType(Scope *sc)
|
||||
|
||||
// Give error for overloaded function addresses
|
||||
if (exp->op == TOKsymoff)
|
||||
{ SymOffExp *se = (SymOffExp *)exp;
|
||||
{
|
||||
SymOffExp *se = (SymOffExp *)exp;
|
||||
if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
|
||||
{
|
||||
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
|
||||
return Type::terror;
|
||||
}
|
||||
}
|
||||
|
||||
// Give error for overloaded function addresses
|
||||
if (exp->op == TOKdelegate)
|
||||
{ DelegateExp *se = (DelegateExp *)exp;
|
||||
{
|
||||
DelegateExp *se = (DelegateExp *)exp;
|
||||
if (se->hasOverloads &&
|
||||
se->func->isFuncDeclaration() &&
|
||||
!se->func->isFuncDeclaration()->isUnique())
|
||||
@@ -1085,6 +1040,15 @@ Type *ExpInitializer::inferType(Scope *sc)
|
||||
return Type::terror;
|
||||
}
|
||||
}
|
||||
if (exp->op == TOKaddress)
|
||||
{
|
||||
AddrExp *ae = (AddrExp *)exp;
|
||||
if (ae->e1->op == TOKoverloadset)
|
||||
{
|
||||
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
|
||||
return Type::terror;
|
||||
}
|
||||
}
|
||||
|
||||
Type *t = exp->type;
|
||||
if (!t)
|
||||
|
||||
+22
-21
@@ -16,17 +16,17 @@
|
||||
#include "mars.h"
|
||||
#include "arraytypes.h"
|
||||
|
||||
struct Identifier;
|
||||
struct Expression;
|
||||
class Identifier;
|
||||
class Expression;
|
||||
struct Scope;
|
||||
struct Type;
|
||||
class Type;
|
||||
struct dt_t;
|
||||
struct AggregateDeclaration;
|
||||
struct ErrorInitializer;
|
||||
struct VoidInitializer;
|
||||
struct StructInitializer;
|
||||
struct ArrayInitializer;
|
||||
struct ExpInitializer;
|
||||
class AggregateDeclaration;
|
||||
class ErrorInitializer;
|
||||
class VoidInitializer;
|
||||
class StructInitializer;
|
||||
class ArrayInitializer;
|
||||
class ExpInitializer;
|
||||
struct HdrGenState;
|
||||
|
||||
#if IN_LLVM
|
||||
@@ -37,8 +37,9 @@ namespace llvm {
|
||||
|
||||
enum NeedInterpret { INITnointerpret, INITinterpret };
|
||||
|
||||
struct Initializer : Object
|
||||
class Initializer : public RootObject
|
||||
{
|
||||
public:
|
||||
Loc loc;
|
||||
|
||||
Initializer(Loc loc);
|
||||
@@ -63,8 +64,9 @@ struct Initializer : Object
|
||||
virtual ExpInitializer *isExpInitializer() { return NULL; }
|
||||
};
|
||||
|
||||
struct VoidInitializer : Initializer
|
||||
class VoidInitializer : public Initializer
|
||||
{
|
||||
public:
|
||||
Type *type; // type that this will initialize to
|
||||
|
||||
VoidInitializer(Loc loc);
|
||||
@@ -80,8 +82,9 @@ struct VoidInitializer : Initializer
|
||||
virtual VoidInitializer *isVoidInitializer() { return this; }
|
||||
};
|
||||
|
||||
struct ErrorInitializer : Initializer
|
||||
class ErrorInitializer : public Initializer
|
||||
{
|
||||
public:
|
||||
ErrorInitializer();
|
||||
Initializer *syntaxCopy();
|
||||
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
|
||||
@@ -91,19 +94,18 @@ struct ErrorInitializer : Initializer
|
||||
virtual ErrorInitializer *isErrorInitializer() { return this; }
|
||||
};
|
||||
|
||||
struct StructInitializer : Initializer
|
||||
class StructInitializer : public Initializer
|
||||
{
|
||||
public:
|
||||
Identifiers field; // of Identifier *'s
|
||||
Initializers value; // parallel array of Initializer *'s
|
||||
|
||||
VarDeclarations vars; // parallel array of VarDeclaration *'s
|
||||
AggregateDeclaration *ad; // which aggregate this is for
|
||||
|
||||
StructInitializer(Loc loc);
|
||||
Initializer *syntaxCopy();
|
||||
void addInit(Identifier *field, Initializer *value);
|
||||
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
|
||||
Expression *toExpression(Type *t = NULL);
|
||||
Expression *fill(Scope *sc, Type *t, NeedInterpret needInterpret);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
#if IN_DMD
|
||||
@@ -111,13 +113,11 @@ struct StructInitializer : Initializer
|
||||
#endif
|
||||
|
||||
StructInitializer *isStructInitializer() { return this; }
|
||||
#if IN_LLVM
|
||||
llvm::StructType *ltype;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ArrayInitializer : Initializer
|
||||
class ArrayInitializer : public Initializer
|
||||
{
|
||||
public:
|
||||
Expressions index; // indices
|
||||
Initializers value; // of Initializer *'s
|
||||
size_t dim; // length of array being initialized
|
||||
@@ -141,8 +141,9 @@ struct ArrayInitializer : Initializer
|
||||
ArrayInitializer *isArrayInitializer() { return this; }
|
||||
};
|
||||
|
||||
struct ExpInitializer : Initializer
|
||||
class ExpInitializer : public Initializer
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
int expandTuples;
|
||||
|
||||
|
||||
+72
-15
@@ -293,7 +293,7 @@ int DeclarationExp::inlineCost3(InlineCostState *ics)
|
||||
return COST_MAX; // finish DeclarationExp::doInline
|
||||
#else
|
||||
for (size_t i = 0; i < td->objects->dim; i++)
|
||||
{ Object *o = (*td->objects)[i];
|
||||
{ RootObject *o = (*td->objects)[i];
|
||||
if (o->dyncast() != DYNCAST_EXPRESSION)
|
||||
return COST_MAX;
|
||||
Expression *eo = (Expression *)o;
|
||||
@@ -665,11 +665,69 @@ Expression *VarExp::doInline(InlineDoState *ids)
|
||||
}
|
||||
}
|
||||
if (ids->fd && var == ids->fd->vthis)
|
||||
{ VarExp *ve = new VarExp(loc, ids->vthis);
|
||||
{
|
||||
VarExp *ve = new VarExp(loc, ids->vthis);
|
||||
ve->type = type;
|
||||
return ve;
|
||||
}
|
||||
|
||||
/* Inlining context pointer access for nested referenced variables.
|
||||
* For example:
|
||||
* auto fun() {
|
||||
* int i = 40;
|
||||
* auto foo() {
|
||||
* int g = 2;
|
||||
* struct Result {
|
||||
* auto bar() { return i + g; }
|
||||
* }
|
||||
* return Result();
|
||||
* }
|
||||
* return foo();
|
||||
* }
|
||||
* auto t = fun();
|
||||
* 'i' and 'g' are nested referenced variables in Result.bar(), so:
|
||||
* auto x = t.bar();
|
||||
* should be inlined to:
|
||||
* auto x = *(t.vthis.vthis + i->voffset) + *(t.vthis + g->voffset)
|
||||
*/
|
||||
VarDeclaration *v = var->isVarDeclaration();
|
||||
if (v && v->nestedrefs.dim && ids->vthis)
|
||||
{
|
||||
Dsymbol *s = ids->fd;
|
||||
FuncDeclaration *fdv = v->toParent()->isFuncDeclaration();
|
||||
assert(fdv);
|
||||
Expression *ve = new VarExp(loc, ids->vthis);
|
||||
ve->type = ids->vthis->type;
|
||||
while (s != fdv)
|
||||
{
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
if (AggregateDeclaration *ad = s->isThis())
|
||||
{
|
||||
assert(ad->vthis);
|
||||
ve = new DotVarExp(loc, ve, ad->vthis);
|
||||
ve->type = ad->vthis->type;
|
||||
s = ad->toParent2();
|
||||
}
|
||||
else if (f && f->isNested())
|
||||
{
|
||||
assert(f->vthis);
|
||||
if (f->hasNestedFrameRefs())
|
||||
{
|
||||
ve = new DotVarExp(loc, ve, f->vthis);
|
||||
ve->type = f->vthis->type;
|
||||
}
|
||||
s = f->toParent2();
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
assert(s);
|
||||
}
|
||||
ve = new DotVarExp(loc, ve, v);
|
||||
ve->type = v->type;
|
||||
//printf("\t==> ve = %s, type = %s\n", ve->toChars(), ve->type->toChars());
|
||||
return ve;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -724,7 +782,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids)
|
||||
VarDeclaration *vto;
|
||||
|
||||
vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
|
||||
*vto = *vd;
|
||||
memcpy((void*)vto, (void*)vd, sizeof(VarDeclaration));
|
||||
vto->parent = ids->parent;
|
||||
#if IN_DMD
|
||||
vto->csym = NULL;
|
||||
@@ -820,7 +878,7 @@ Expression *IndexExp::doInline(InlineDoState *ids)
|
||||
VarDeclaration *vto;
|
||||
|
||||
vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
|
||||
*vto = *vd;
|
||||
memcpy((void*)vto, (void*)vd, sizeof(VarDeclaration));
|
||||
vto->parent = ids->parent;
|
||||
#if IN_DMD
|
||||
vto->csym = NULL;
|
||||
@@ -859,7 +917,7 @@ Expression *SliceExp::doInline(InlineDoState *ids)
|
||||
VarDeclaration *vto;
|
||||
|
||||
vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
|
||||
*vto = *vd;
|
||||
memcpy((void*)vto, (void*)vd, sizeof(VarDeclaration));
|
||||
vto->parent = ids->parent;
|
||||
#if IN_DMD
|
||||
vto->csym = NULL;
|
||||
@@ -1133,12 +1191,7 @@ Statement *ReturnStatement::inlineScan(InlineScanState *iss)
|
||||
{
|
||||
//printf("ReturnStatement::inlineScan()\n");
|
||||
if (exp)
|
||||
{
|
||||
exp = exp->inlineScan(iss);
|
||||
|
||||
FuncDeclaration *func = iss->fd;
|
||||
TypeFunction *tf = (TypeFunction *)(func->type);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1230,6 +1283,7 @@ Expression *Expression::inlineScan(InlineScanState *iss)
|
||||
|
||||
void scanVar(Dsymbol *s, InlineScanState *iss)
|
||||
{
|
||||
//printf("scanVar(%s %s)\n", s->kind(), s->toPrettyChars());
|
||||
VarDeclaration *vd = s->isVarDeclaration();
|
||||
if (vd)
|
||||
{
|
||||
@@ -1281,6 +1335,10 @@ void scanVar(Dsymbol *s, InlineScanState *iss)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->inlineScan();
|
||||
}
|
||||
}
|
||||
|
||||
Expression *DeclarationExp::inlineScan(InlineScanState *iss)
|
||||
@@ -1438,7 +1496,7 @@ void FuncDeclaration::inlineScan()
|
||||
InlineScanState iss;
|
||||
|
||||
#if LOG
|
||||
printf("FuncDeclaration::inlineScan('%s')\n", toChars());
|
||||
printf("FuncDeclaration::inlineScan('%s')\n", toPrettyChars());
|
||||
#endif
|
||||
memset(&iss, 0, sizeof(iss));
|
||||
iss.fd = this;
|
||||
@@ -1458,7 +1516,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
|
||||
#define CANINLINE_LOG 0
|
||||
|
||||
#if CANINLINE_LOG
|
||||
printf("FuncDeclaration::canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, toChars());
|
||||
printf("FuncDeclaration::canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, toPrettyChars());
|
||||
#endif
|
||||
|
||||
if (needThis() && !hasthis)
|
||||
@@ -1535,10 +1593,8 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
|
||||
#endif
|
||||
isSynchronized() ||
|
||||
isImportedSymbol() ||
|
||||
//#if !IN_LLVM
|
||||
hasNestedFrameRefs() || // no nested references to this frame
|
||||
//#endif // !IN_LLVM
|
||||
(isVirtual() && !isFinal())
|
||||
(isVirtual() && !isFinalFunc())
|
||||
))
|
||||
{
|
||||
goto Lno;
|
||||
@@ -1749,6 +1805,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
||||
//eb->print();
|
||||
//eb->dump(0);
|
||||
}
|
||||
//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'.
|
||||
|
||||
+1402
-684
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -13,8 +13,8 @@
|
||||
#define DMD_SXNUM_H
|
||||
|
||||
#include "mars.h" // for uinteger_t
|
||||
struct Type;
|
||||
struct Expression;
|
||||
class Type;
|
||||
class Expression;
|
||||
|
||||
/**
|
||||
This class represents a "sign-extended number", i.e. a 65-bit number, which can
|
||||
|
||||
+13
-13
@@ -68,9 +68,9 @@ struct JsonOut
|
||||
void property(const char *name, Type* type);
|
||||
void property(const char *name, const char *deconame, Type* type);
|
||||
void property(const char *name, Parameters* parameters);
|
||||
void property(const char *name, enum TRUST trust);
|
||||
void property(const char *name, enum PURE purity);
|
||||
void property(const char *name, enum LINK linkage);
|
||||
void property(const char *name, TRUST trust);
|
||||
void property(const char *name, PURE purity);
|
||||
void property(const char *name, LINK linkage);
|
||||
};
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ void json_generate(OutBuffer *buf, Modules *modules)
|
||||
for (size_t i = 0; i < modules->dim; i++)
|
||||
{ Module *m = (*modules)[i];
|
||||
if (global.params.verbose)
|
||||
printf("json gen %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "json gen %s\n", m->toChars());
|
||||
m->toJson(&json);
|
||||
}
|
||||
json.arrayEnd();
|
||||
@@ -128,7 +128,7 @@ void JsonOut::stringPart(const char *s)
|
||||
{
|
||||
for (; *s; s++)
|
||||
{
|
||||
unsigned char c = (unsigned char) *s;
|
||||
utf8_t c = (utf8_t) *s;
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
@@ -307,7 +307,7 @@ void JsonOut::propertyBool(const char *name, bool b)
|
||||
}
|
||||
|
||||
|
||||
void JsonOut::property(const char *name, enum TRUST trust)
|
||||
void JsonOut::property(const char *name, TRUST trust)
|
||||
{
|
||||
switch (trust)
|
||||
{
|
||||
@@ -329,7 +329,7 @@ void JsonOut::property(const char *name, enum TRUST trust)
|
||||
}
|
||||
}
|
||||
|
||||
void JsonOut::property(const char *name, enum PURE purity)
|
||||
void JsonOut::property(const char *name, PURE purity)
|
||||
{
|
||||
switch (purity)
|
||||
{
|
||||
@@ -354,7 +354,7 @@ void JsonOut::property(const char *name, enum PURE purity)
|
||||
}
|
||||
}
|
||||
|
||||
void JsonOut::property(const char *name, enum LINK linkage)
|
||||
void JsonOut::property(const char *name, LINK linkage)
|
||||
{
|
||||
switch (linkage)
|
||||
{
|
||||
@@ -395,7 +395,7 @@ void JsonOut::propertyStorageClass(const char *name, StorageClass stc)
|
||||
{ char tmp[20];
|
||||
const char *p = StorageClassDeclaration::stcToChars(tmp, stc);
|
||||
assert(p);
|
||||
assert(strlen(p) < sizeof(tmp));
|
||||
assert(strlen(p) < sizeof(tmp) / sizeof(tmp[0]));
|
||||
if (p[0] == '@')
|
||||
{
|
||||
indent();
|
||||
@@ -544,7 +544,7 @@ void TypeQualified::toJson(JsonOut *json) // ident.ident.ident.etc
|
||||
json->arrayStart();
|
||||
|
||||
for (size_t i = 0; i < idents.dim; i++)
|
||||
{ Object *ident = idents[i];
|
||||
{ RootObject *ident = idents[i];
|
||||
json->item(ident->toChars());
|
||||
}
|
||||
|
||||
@@ -806,7 +806,6 @@ void ConditionalDeclaration::toJson(JsonOut *json)
|
||||
|
||||
|
||||
void ClassInfoDeclaration::toJson(JsonOut *json) { }
|
||||
void ModuleInfoDeclaration::toJson(JsonOut *json) { }
|
||||
void TypeInfoDeclaration::toJson(JsonOut *json) { }
|
||||
#if DMDV2
|
||||
void PostBlitDeclaration::toJson(JsonOut *json) { }
|
||||
@@ -971,9 +970,10 @@ void TemplateDeclaration::toJson(JsonOut *json)
|
||||
if (s->isTemplateThisParameter())
|
||||
json->property("kind", "this");
|
||||
else
|
||||
#endif
|
||||
json->property("kind", "type");
|
||||
|
||||
#else
|
||||
json->property("kind", "type");
|
||||
#endif
|
||||
json->property("type", "deco", type->specType);
|
||||
|
||||
json->property("default", "defaultDeco", type->defaultType);
|
||||
|
||||
+145
-227
File diff suppressed because it is too large
Load Diff
+19
-24
@@ -19,8 +19,8 @@
|
||||
#include "mars.h"
|
||||
|
||||
struct StringTable;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
class Identifier;
|
||||
class Module;
|
||||
|
||||
/* Tokens:
|
||||
( )
|
||||
@@ -69,6 +69,8 @@ enum TOK
|
||||
TOKnewanonclass, TOKcomment,
|
||||
TOKarrayliteral, TOKassocarrayliteral,
|
||||
TOKstructliteral,
|
||||
TOKclassreference,
|
||||
TOKthrownexception,
|
||||
|
||||
// Operators
|
||||
TOKlt, TOKgt,
|
||||
@@ -229,10 +231,11 @@ enum TOK
|
||||
struct Token
|
||||
{
|
||||
Token *next;
|
||||
unsigned char *ptr; // pointer to first character of this token within buffer
|
||||
enum TOK value;
|
||||
unsigned char *blockComment; // doc comment string prior to this token
|
||||
unsigned char *lineComment; // doc comment for previous token
|
||||
Loc loc;
|
||||
utf8_t *ptr; // pointer to first character of this token within buffer
|
||||
TOK value;
|
||||
utf8_t *blockComment; // doc comment string prior to this token
|
||||
utf8_t *lineComment; // doc comment for previous token
|
||||
union
|
||||
{
|
||||
// Integers
|
||||
@@ -242,23 +245,16 @@ struct Token
|
||||
d_uns64 uns64value;
|
||||
|
||||
// Floats
|
||||
#ifdef IN_GCC
|
||||
// real_t float80value; // can't use this in a union!
|
||||
#else
|
||||
d_float80 float80value;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{ unsigned char *ustring; // UTF8 string
|
||||
{ utf8_t *ustring; // UTF8 string
|
||||
unsigned len;
|
||||
unsigned char postfix; // 'c', 'w', 'd'
|
||||
};
|
||||
|
||||
Identifier *ident;
|
||||
};
|
||||
#ifdef IN_GCC
|
||||
real_t float80value; // can't use this in a union!
|
||||
#endif
|
||||
|
||||
static const char *tochars[TOKMAX];
|
||||
static void *operator new(size_t sz);
|
||||
@@ -269,20 +265,21 @@ struct Token
|
||||
void print();
|
||||
#endif
|
||||
const char *toChars();
|
||||
static const char *toChars(enum TOK);
|
||||
static const char *toChars(TOK);
|
||||
};
|
||||
|
||||
struct Lexer
|
||||
class Lexer
|
||||
{
|
||||
public:
|
||||
static StringTable stringtable;
|
||||
static OutBuffer stringbuffer;
|
||||
static Token *freelist;
|
||||
|
||||
Loc loc; // for error messages
|
||||
Loc scanloc; // for error messages
|
||||
|
||||
unsigned char *base; // pointer to start of buffer
|
||||
unsigned char *end; // past end of buffer
|
||||
unsigned char *p; // current character
|
||||
utf8_t *base; // pointer to start of buffer
|
||||
utf8_t *end; // past end of buffer
|
||||
utf8_t *p; // current character
|
||||
Token token;
|
||||
Module *mod;
|
||||
int doDocComment; // collect doc comment information
|
||||
@@ -290,7 +287,7 @@ struct Lexer
|
||||
int commentToken; // !=0 means comments are TOKcomment's
|
||||
|
||||
Lexer(Module *mod,
|
||||
unsigned char *base, size_t begoffset, size_t endoffset,
|
||||
utf8_t *base, size_t begoffset, size_t endoffset,
|
||||
int doDocComment, int commentToken);
|
||||
|
||||
static void initKeywords();
|
||||
@@ -324,9 +321,7 @@ struct Lexer
|
||||
void getDocComment(Token *t, unsigned lineComment);
|
||||
|
||||
static int isValidIdentifier(char *p);
|
||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||
|
||||
Loc tokenLoc();
|
||||
static utf8_t *combineComments(utf8_t *c1, utf8_t *c2);
|
||||
};
|
||||
|
||||
#endif /* DMD_LEXER_H */
|
||||
|
||||
+18
-18
@@ -21,16 +21,16 @@
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
int isIdStart(unsigned char *p);
|
||||
int isIdTail(unsigned char *p);
|
||||
int utfStride(unsigned char *p);
|
||||
int isIdStart(utf8_t *p);
|
||||
int isIdTail(utf8_t *p);
|
||||
int utfStride(utf8_t *p);
|
||||
|
||||
unsigned char *memdup(unsigned char *p, size_t len)
|
||||
utf8_t *memdup(utf8_t *p, size_t len)
|
||||
{
|
||||
return (unsigned char *)memcpy(mem.malloc(len), p, len);
|
||||
return (utf8_t *)memcpy(mem.malloc(len), p, len);
|
||||
}
|
||||
|
||||
Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
|
||||
Macro::Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen)
|
||||
{
|
||||
next = NULL;
|
||||
|
||||
@@ -51,7 +51,7 @@ Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t te
|
||||
}
|
||||
|
||||
|
||||
Macro *Macro::search(unsigned char *name, size_t namelen)
|
||||
Macro *Macro::search(utf8_t *name, size_t namelen)
|
||||
{ Macro *table;
|
||||
|
||||
//printf("Macro::search(%.*s)\n", namelen, name);
|
||||
@@ -67,7 +67,7 @@ Macro *Macro::search(unsigned char *name, size_t namelen)
|
||||
return table;
|
||||
}
|
||||
|
||||
Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen)
|
||||
Macro *Macro::define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text, size_t textlen)
|
||||
{
|
||||
//printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text);
|
||||
|
||||
@@ -98,7 +98,7 @@ Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsign
|
||||
* -1: get 2nd through end
|
||||
*/
|
||||
|
||||
size_t extractArgN(unsigned char *p, size_t end, unsigned char **pmarg, size_t *pmarglen, int n)
|
||||
size_t extractArgN(utf8_t *p, size_t end, utf8_t **pmarg, size_t *pmarglen, int n)
|
||||
{
|
||||
/* Scan forward for matching right parenthesis.
|
||||
* Nest parentheses.
|
||||
@@ -130,7 +130,7 @@ size_t extractArgN(unsigned char *p, size_t end, unsigned char **pmarg, size_t *
|
||||
*pmarg = p + v;
|
||||
|
||||
for (; v < end; v++)
|
||||
{ unsigned char c = p[v];
|
||||
{ utf8_t c = p[v];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
@@ -238,7 +238,7 @@ size_t extractArgN(unsigned char *p, size_t end, unsigned char **pmarg, size_t *
|
||||
*/
|
||||
|
||||
void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||
unsigned char *arg, size_t arglen)
|
||||
utf8_t *arg, size_t arglen)
|
||||
{
|
||||
#if 0
|
||||
printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg);
|
||||
@@ -259,7 +259,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||
arg = memdup(arg, arglen);
|
||||
for (size_t u = start; u + 1 < end; )
|
||||
{
|
||||
unsigned char *p = buf->data; // buf->data is not loop invariant
|
||||
utf8_t *p = buf->data; // buf->data is not loop invariant
|
||||
|
||||
/* Look for $0, but not $$0, and replace it with arg.
|
||||
*/
|
||||
@@ -273,10 +273,10 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char c = p[u + 1];
|
||||
utf8_t c = p[u + 1];
|
||||
int n = (c == '+') ? -1 : c - '0';
|
||||
|
||||
unsigned char *marg;
|
||||
utf8_t *marg;
|
||||
size_t marglen;
|
||||
extractArgN(arg, arglen, &marg, &marglen, n);
|
||||
if (marglen == 0)
|
||||
@@ -327,7 +327,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||
*/
|
||||
for (size_t u = start; u + 4 < end; )
|
||||
{
|
||||
unsigned char *p = buf->data; // buf->data is not loop invariant
|
||||
utf8_t *p = buf->data; // buf->data is not loop invariant
|
||||
|
||||
/* A valid start of macro expansion is $(c, where c is
|
||||
* an id start character, and not $$(c.
|
||||
@@ -335,10 +335,10 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||
if (p[u] == '$' && p[u + 1] == '(' && isIdStart(p+u+2))
|
||||
{
|
||||
//printf("\tfound macro start '%c'\n", p[u + 2]);
|
||||
unsigned char *name = p + u + 2;
|
||||
utf8_t *name = p + u + 2;
|
||||
size_t namelen = 0;
|
||||
|
||||
unsigned char *marg;
|
||||
utf8_t *marg;
|
||||
size_t marglen;
|
||||
|
||||
size_t v;
|
||||
@@ -346,7 +346,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||
* beginning of macro argument (marg).
|
||||
*/
|
||||
for (v = u + 2; v < end; v+=utfStride(p+v))
|
||||
{ unsigned char c = p[v];
|
||||
{ utf8_t c = p[v];
|
||||
|
||||
if (!isIdTail(p+v))
|
||||
{ // We've gone past the end of the macro name.
|
||||
|
||||
+6
-6
@@ -24,22 +24,22 @@ struct Macro
|
||||
private:
|
||||
Macro *next; // next in list
|
||||
|
||||
unsigned char *name; // macro name
|
||||
utf8_t *name; // macro name
|
||||
size_t namelen; // length of macro name
|
||||
|
||||
unsigned char *text; // macro replacement text
|
||||
utf8_t *text; // macro replacement text
|
||||
size_t textlen; // length of replacement text
|
||||
|
||||
int inuse; // macro is in use (don't expand)
|
||||
|
||||
Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
|
||||
Macro *search(unsigned char *name, size_t namelen);
|
||||
Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen);
|
||||
Macro *search(utf8_t *name, size_t namelen);
|
||||
|
||||
public:
|
||||
static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen);
|
||||
static Macro *define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text, size_t textlen);
|
||||
|
||||
void expand(OutBuffer *buf, size_t start, size_t *pend,
|
||||
unsigned char *arg, size_t arglen);
|
||||
utf8_t *arg, size_t arglen);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+64
-8
@@ -46,7 +46,7 @@ char *mangle(Declaration *sthis, bool isv)
|
||||
do
|
||||
{
|
||||
//printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
|
||||
if (s->ident)
|
||||
if (s->getIdent())
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (s != sthis && fd)
|
||||
@@ -79,6 +79,17 @@ L1:
|
||||
buf.writeByte(Type::needThisPrefix());
|
||||
if (isv && fd && (fd->inferRetType || getFuncTemplateDecl(fd)))
|
||||
{
|
||||
#if DDMD
|
||||
TypeFunction *tfn = (TypeFunction *)sthis->type->copy();
|
||||
TypeFunction *tfo = (TypeFunction *)sthis->originalType;
|
||||
tfn->purity = tfo->purity;
|
||||
tfn->isnothrow = tfo->isnothrow;
|
||||
tfn->isproperty = tfo->isproperty;
|
||||
tfn->isref = fd->storage_class & STCauto ? false : tfo->isref;
|
||||
tfn->trust = tfo->trust;
|
||||
tfn->next = NULL; // do not mangle return type
|
||||
tfn->toDecoBuffer(&buf, 0);
|
||||
#else
|
||||
TypeFunction tfn = *(TypeFunction *)sthis->type;
|
||||
TypeFunction *tfo = (TypeFunction *)sthis->originalType;
|
||||
tfn.purity = tfo->purity;
|
||||
@@ -88,6 +99,7 @@ L1:
|
||||
tfn.trust = tfo->trust;
|
||||
tfn.next = NULL; // do not mangle return type
|
||||
tfn.toDecoBuffer(&buf, 0);
|
||||
#endif
|
||||
}
|
||||
else if (sthis->type->deco)
|
||||
buf.writestring(sthis->type->deco);
|
||||
@@ -167,7 +179,49 @@ const char *Declaration::mangle(bool isv)
|
||||
return p;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Normally FuncDeclaration and FuncAliasDeclaration have overloads.
|
||||
* If and only if there is no overloads, mangle() could return
|
||||
* exact mangled name.
|
||||
*
|
||||
* module test;
|
||||
* void foo(long) {} // _D4test3fooFlZv
|
||||
* void foo(string) {} // _D4test3fooFAyaZv
|
||||
*
|
||||
* // from FuncDeclaration::mangle().
|
||||
* pragma(msg, foo.mangleof); // prints unexact mangled name "4test3foo"
|
||||
* // by calling Dsymbol::mangle()
|
||||
*
|
||||
* // from FuncAliasDeclaration::mangle()
|
||||
* pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof); // "_D4test3fooFlZv"
|
||||
* pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof); // "_D4test3fooFAyaZv"
|
||||
*
|
||||
* If a function has no overloads, .mangleof property still returns exact mangled name.
|
||||
*
|
||||
* void bar() {}
|
||||
* pragma(msg, bar.mangleof); // still prints "_D4test3barFZv"
|
||||
* // by calling FuncDeclaration::mangleExact().
|
||||
*/
|
||||
const char *FuncDeclaration::mangle(bool isv)
|
||||
{
|
||||
return isUnique() ? mangleExact(isv) : Dsymbol::mangle(isv);
|
||||
}
|
||||
// ditto
|
||||
const char *FuncAliasDeclaration::mangle(bool isv)
|
||||
{
|
||||
FuncDeclaration *f = toAliasFunc();
|
||||
FuncAliasDeclaration *fa = f->isFuncAliasDeclaration();
|
||||
if (!hasOverloads && !fa)
|
||||
return f->mangleExact(isv);
|
||||
if (fa)
|
||||
return fa->mangle(isv);
|
||||
return Dsymbol::mangle(isv);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Returns exact mangled name of function.
|
||||
*/
|
||||
const char *FuncDeclaration::mangleExact(bool isv)
|
||||
#if __DMC__
|
||||
__out(result)
|
||||
{
|
||||
@@ -176,9 +230,11 @@ const char *FuncDeclaration::mangle(bool isv)
|
||||
__body
|
||||
#endif
|
||||
{
|
||||
assert(!isFuncAliasDeclaration());
|
||||
|
||||
if (mangleOverride)
|
||||
return mangleOverride;
|
||||
|
||||
return mangleOverride;
|
||||
|
||||
if (isMain())
|
||||
return (char *)"_Dmain";
|
||||
|
||||
@@ -253,10 +309,8 @@ const char *ClassDeclaration::mangle(bool isv)
|
||||
ident == Id::TypeInfo_Typedef ||
|
||||
ident == Id::TypeInfo_Tuple ||
|
||||
this == object ||
|
||||
this == classinfo ||
|
||||
#if !MODULEINFO_IS_STRUCT
|
||||
this == Type::typeinfoclass ||
|
||||
this == Module::moduleinfo ||
|
||||
#endif
|
||||
memcmp(ident->toChars(), "TypeInfo_", 9) == 0
|
||||
)
|
||||
parent = NULL;
|
||||
@@ -277,6 +331,7 @@ const char *TemplateInstance::mangle(bool isv)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
getIdent();
|
||||
const char *id = ident ? ident->toChars() : toChars();
|
||||
if (!tempdecl)
|
||||
error("is not defined");
|
||||
@@ -285,7 +340,7 @@ const char *TemplateInstance::mangle(bool isv)
|
||||
Dsymbol *par = enclosing || isTemplateMixin() ? parent : tempdecl->parent;
|
||||
if (par)
|
||||
{
|
||||
const char *p = par->mangle();
|
||||
const char *p = par->mangle(isv);
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
@@ -314,7 +369,8 @@ const char *Dsymbol::mangle(bool isv)
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
if (parent)
|
||||
{
|
||||
const char *p = parent->mangle(isv);
|
||||
FuncDeclaration *f = parent->isFuncDeclaration();
|
||||
const char *p = f ? f->mangleExact(isv) : parent->mangle(isv);
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
|
||||
+213
-66
@@ -29,12 +29,14 @@
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
#include "scope.h"
|
||||
#include "mtype.h"
|
||||
#include "id.h"
|
||||
#include "cond.h"
|
||||
#include "expression.h"
|
||||
#include "lexer.h"
|
||||
#if !IN_LLVM
|
||||
#include "parse.h"
|
||||
#include "lib.h"
|
||||
#include "json.h"
|
||||
#endif
|
||||
@@ -57,6 +59,36 @@ void printCtfePerformanceStats();
|
||||
|
||||
static bool parse_arch(size_t argc, char** argv, bool is64bit);
|
||||
|
||||
/** Normalize path by turning forward slashes into backslashes */
|
||||
void toWinPath(char *src)
|
||||
{
|
||||
if (src == NULL)
|
||||
return;
|
||||
|
||||
while (*src != '\0')
|
||||
{
|
||||
if (*src == '/')
|
||||
*src = '\\';
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
Ungag::~Ungag()
|
||||
{
|
||||
//printf("+ungag dtor gag %d => %d\n", global.gag, oldgag);
|
||||
global.gag = oldgag;
|
||||
}
|
||||
|
||||
Ungag Dsymbol::ungagSpeculative()
|
||||
{
|
||||
unsigned oldgag = global.gag;
|
||||
|
||||
if (global.isSpeculativeGagging() && !isSpeculative())
|
||||
global.gag = 0;
|
||||
|
||||
return Ungag(oldgag);
|
||||
}
|
||||
|
||||
Global global;
|
||||
|
||||
void Global::init()
|
||||
@@ -104,6 +136,7 @@ void Global::init()
|
||||
#if IN_LLVM
|
||||
compiler.vendor = "LDC";
|
||||
#endif
|
||||
stdmsg = stdout;
|
||||
|
||||
main_d = "__main.d";
|
||||
|
||||
@@ -137,6 +170,13 @@ bool Global::isSpeculativeGagging()
|
||||
return gag && gag == speculativeGag;
|
||||
}
|
||||
|
||||
void Global::increaseErrorCount()
|
||||
{
|
||||
if (gag)
|
||||
++gaggedErrors;
|
||||
++errors;
|
||||
}
|
||||
|
||||
|
||||
char *Loc::toChars()
|
||||
{
|
||||
@@ -233,6 +273,7 @@ void verrorPrint(Loc loc, const char *header, const char *format, va_list ap,
|
||||
}
|
||||
|
||||
// header is "Error: " by default (see mars.h)
|
||||
extern "C" {
|
||||
void verror(Loc loc, const char *format, va_list ap,
|
||||
const char *p1, const char *p2, const char *header)
|
||||
{
|
||||
@@ -249,6 +290,7 @@ void verror(Loc loc, const char *format, va_list ap,
|
||||
}
|
||||
global.errors++;
|
||||
}
|
||||
}
|
||||
|
||||
// Doesn't increase error count, doesn't print "Error:".
|
||||
void verrorSupplemental(Loc loc, const char *format, va_list ap)
|
||||
@@ -328,7 +370,7 @@ Usage:\n\
|
||||
@cmdfile read arguments from cmdfile\n\
|
||||
-c do not link\n\
|
||||
-cov do code coverage analysis\n\
|
||||
-cov=nnn require at least %%nnn code coverage\n\
|
||||
-cov=nnn require at least nnn%% code coverage\n\
|
||||
-D generate documentation\n\
|
||||
-Dddocdir write documentation file to docdir directory\n\
|
||||
-Dffilename write documentation file to filename\n\
|
||||
@@ -340,8 +382,9 @@ Usage:\n\
|
||||
-debug=ident compile in debug code identified by ident\n\
|
||||
-debuglib=name set symbolic debug library to name\n\
|
||||
-defaultlib=name set default library to name\n\
|
||||
-deps=filename write module dependencies to filename\n%s"
|
||||
" -g add symbolic debug info\n\
|
||||
-deps print module dependencies (imports/file/version/debug/lib)\n\
|
||||
-deps=filename write module dependencies to filename (only imports - deprecated)\n%s\
|
||||
-g add symbolic debug info\n\
|
||||
-gc add symbolic debug info, pretend to be C\n\
|
||||
-gs always emit stack frame\n\
|
||||
-gx add stack stomp code\n\
|
||||
@@ -354,12 +397,10 @@ Usage:\n\
|
||||
-inline do function inlining\n\
|
||||
-Jpath where to look for string imports\n\
|
||||
-Llinkerflag pass linkerflag to link\n\
|
||||
-lib generate library rather than object files\n"
|
||||
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
|
||||
" -m32 generate 32 bit code\n\
|
||||
-m64 generate 64 bit code\n"
|
||||
#endif
|
||||
" -main add default main() (e.g. for unittesting)\n\
|
||||
-lib generate library rather than object files\n\
|
||||
-m32 generate 32 bit code\n\
|
||||
-m64 generate 64 bit code\n\
|
||||
-main add default main() (e.g. for unittesting)\n\
|
||||
-man open web browser on manual page\n\
|
||||
-map generate linker .map file\n\
|
||||
-noboundscheck turns off array bounds checking for all functions\n\
|
||||
@@ -398,6 +439,52 @@ extern "C"
|
||||
}
|
||||
#endif
|
||||
|
||||
static Module *entrypoint = NULL;
|
||||
|
||||
/************************************
|
||||
* Generate C main() in response to seeing D main().
|
||||
* This used to be in druntime, but contained a reference to _Dmain
|
||||
* which didn't work when druntime was made into a dll and was linked
|
||||
* to a program, such as a C++ program, that didn't have a _Dmain.
|
||||
*/
|
||||
|
||||
void genCmain(Scope *sc)
|
||||
{
|
||||
if (entrypoint)
|
||||
return;
|
||||
|
||||
/* The D code to be generated is provided as D source code in the form of a string.
|
||||
* Note that Solaris, for unknown reasons, requires both a main() and an _main()
|
||||
*/
|
||||
static utf8_t code[] = "extern(C) {\n\
|
||||
int _d_run_main(int argc, char **argv, void* mainFunc);\n\
|
||||
int _Dmain(char[][] args);\n\
|
||||
int main(int argc, char **argv) { return _d_run_main(argc, argv, &_Dmain); }\n\
|
||||
version (Solaris) int _main(int argc, char** argv) { return main(argc, argv); }\n\
|
||||
}\n\
|
||||
";
|
||||
|
||||
Identifier *id = Id::entrypoint;
|
||||
Module *m = new Module("__entrypoint.d", id, 0, 0);
|
||||
|
||||
Parser p(m, code, sizeof(code) / sizeof(code[0]), 0);
|
||||
p.scanloc = Loc();
|
||||
p.nextToken();
|
||||
m->members = p.parseModule();
|
||||
assert(p.token.value == TOKeof);
|
||||
|
||||
char v = global.params.verbose;
|
||||
global.params.verbose = 0;
|
||||
m->importedFrom = sc->module;
|
||||
m->importAll(NULL);
|
||||
m->semantic();
|
||||
m->semantic2();
|
||||
m->semantic3();
|
||||
global.params.verbose = v;
|
||||
|
||||
entrypoint = m;
|
||||
}
|
||||
|
||||
int tryMain(size_t argc, char *argv[])
|
||||
{
|
||||
mem.init(); // initialize storage allocator
|
||||
@@ -452,7 +539,6 @@ int tryMain(size_t argc, char *argv[])
|
||||
global.params.useSwitchError = 1;
|
||||
global.params.useInline = 0;
|
||||
global.params.obj = 1;
|
||||
global.params.Dversion = 2;
|
||||
global.params.quiet = 1;
|
||||
global.params.useDeprecated = 2;
|
||||
|
||||
@@ -564,7 +650,7 @@ int tryMain(size_t argc, char *argv[])
|
||||
// -cov=nnn
|
||||
if (p[4] == '=')
|
||||
{
|
||||
if (isdigit((unsigned char)p[5]))
|
||||
if (isdigit((utf8_t)p[5]))
|
||||
{ long percent;
|
||||
|
||||
errno = 0;
|
||||
@@ -579,17 +665,25 @@ int tryMain(size_t argc, char *argv[])
|
||||
else if (p[4])
|
||||
goto Lerror;
|
||||
}
|
||||
else if (strcmp(p + 1, "shared") == 0
|
||||
#if TARGET_OSX
|
||||
// backwards compatibility with old switch
|
||||
|| strcmp(p + 1, "dylib") == 0
|
||||
#endif
|
||||
)
|
||||
else if (strcmp(p + 1, "shared") == 0)
|
||||
global.params.dll = 1;
|
||||
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
|
||||
else if (strcmp(p + 1, "fPIC") == 0)
|
||||
global.params.pic = 1;
|
||||
else if (strcmp(p + 1, "dylib") == 0)
|
||||
{
|
||||
#if TARGET_OSX
|
||||
warning(Loc(), "use -shared instead of -dylib");
|
||||
global.params.dll = 1;
|
||||
#else
|
||||
goto Lerror;
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(p + 1, "fPIC") == 0)
|
||||
{
|
||||
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
|
||||
global.params.pic = 1;
|
||||
#else
|
||||
goto Lerror;
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(p + 1, "map") == 0)
|
||||
global.params.map = 1;
|
||||
else if (strcmp(p + 1, "multiobj") == 0)
|
||||
@@ -639,7 +733,7 @@ Language changes listed by -transition=id:\n\
|
||||
#endif
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (isdigit((unsigned char)p[12]))
|
||||
if (isdigit((utf8_t)p[12]))
|
||||
{ long num;
|
||||
|
||||
errno = 0;
|
||||
@@ -660,7 +754,7 @@ Language changes listed by -transition=id:\n\
|
||||
if (strcmp(p + 12, "tls") == 0)
|
||||
global.params.vtls = 1;
|
||||
#if PULL93
|
||||
else if (strcmp(p + 12, "field") == 0)
|
||||
if (strcmp(p + 12, "field") == 0)
|
||||
global.params.vfield = 1;
|
||||
#endif
|
||||
}
|
||||
@@ -671,15 +765,6 @@ Language changes listed by -transition=id:\n\
|
||||
goto Lerror;
|
||||
}
|
||||
#endif
|
||||
else if (strcmp(p + 1, "v1") == 0)
|
||||
{
|
||||
#if DMDV1
|
||||
global.params.Dversion = 1;
|
||||
#else
|
||||
error(Loc(), "use DMD 1.0 series compilers for -v1 switch");
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(p + 1, "w") == 0)
|
||||
global.params.warnings = 1;
|
||||
else if (strcmp(p + 1, "wi") == 0)
|
||||
@@ -697,12 +782,18 @@ Language changes listed by -transition=id:\n\
|
||||
case 'd':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
#if _WIN32
|
||||
toWinPath(p + 3);
|
||||
#endif
|
||||
global.params.objdir = p + 3;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
#if _WIN32
|
||||
toWinPath(p + 3);
|
||||
#endif
|
||||
global.params.objname = p + 3;
|
||||
break;
|
||||
|
||||
@@ -824,7 +915,7 @@ Language changes listed by -transition=id:\n\
|
||||
// -debug=identifier
|
||||
if (p[6] == '=')
|
||||
{
|
||||
if (isdigit((unsigned char)p[7]))
|
||||
if (isdigit((utf8_t)p[7]))
|
||||
{ long level;
|
||||
|
||||
errno = 0;
|
||||
@@ -850,7 +941,7 @@ Language changes listed by -transition=id:\n\
|
||||
// -version=identifier
|
||||
if (p[8] == '=')
|
||||
{
|
||||
if (isdigit((unsigned char)p[9]))
|
||||
if (isdigit((utf8_t)p[9]))
|
||||
{ long level;
|
||||
|
||||
errno = 0;
|
||||
@@ -897,11 +988,23 @@ Language changes listed by -transition=id:\n\
|
||||
setdebuglib = 1;
|
||||
global.params.debuglibname = p + 1 + 9;
|
||||
}
|
||||
else if (memcmp(p + 1, "deps=", 5) == 0)
|
||||
else if (memcmp(p + 1, "deps", 4) == 0)
|
||||
{
|
||||
global.params.moduleDepsFile = p + 1 + 5;
|
||||
if (!global.params.moduleDepsFile[0])
|
||||
goto Lnoarg;
|
||||
if(global.params.moduleDeps)
|
||||
{
|
||||
error(Loc(), "-deps[=file] can only be provided once!");
|
||||
break;
|
||||
}
|
||||
if (p[5] == '=')
|
||||
{
|
||||
global.params.moduleDepsFile = p + 1 + 5;
|
||||
if (!global.params.moduleDepsFile[0])
|
||||
goto Lnoarg;
|
||||
} // Else output to stdout.
|
||||
else if (p[5]!='\0')
|
||||
{
|
||||
goto Lerror;
|
||||
}
|
||||
global.params.moduleDeps = new OutBuffer;
|
||||
}
|
||||
else if (strcmp(p + 1, "main") == 0)
|
||||
@@ -999,6 +1102,9 @@ Language changes listed by -transition=id:\n\
|
||||
error(Loc(), "the architecture must not be changed in the %s section of %s",
|
||||
is64bit ? "Environment64" : "Environment32", inifilename);
|
||||
|
||||
// Target uses 64bit pointers.
|
||||
global.params.isLP64 = global.params.is64bit;
|
||||
|
||||
if (global.errors)
|
||||
{
|
||||
fatal();
|
||||
@@ -1095,7 +1201,6 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86_64");
|
||||
VersionCondition::addPredefinedGlobalIdent("X86_64");
|
||||
VersionCondition::addPredefinedGlobalIdent("D_LP64");
|
||||
VersionCondition::addPredefinedGlobalIdent("D_SIMD");
|
||||
#if TARGET_WINDOS
|
||||
VersionCondition::addPredefinedGlobalIdent("Win64");
|
||||
@@ -1118,6 +1223,8 @@ Language changes listed by -transition=id:\n\
|
||||
VersionCondition::addPredefinedGlobalIdent("Win32");
|
||||
#endif
|
||||
}
|
||||
if (global.params.isLP64)
|
||||
VersionCondition::addPredefinedGlobalIdent("D_LP64");
|
||||
if (global.params.doDocComments)
|
||||
VersionCondition::addPredefinedGlobalIdent("D_Ddoc");
|
||||
if (global.params.cov)
|
||||
@@ -1144,9 +1251,9 @@ Language changes listed by -transition=id:\n\
|
||||
initPrecedence();
|
||||
|
||||
if (global.params.verbose)
|
||||
{ printf("binary %s\n", argv[0]);
|
||||
printf("version %s\n", global.version);
|
||||
printf("config %s\n", inifilename ? inifilename : "(none)");
|
||||
{ fprintf(global.stdmsg, "binary %s\n", argv[0]);
|
||||
fprintf(global.stdmsg, "version %s\n", global.version);
|
||||
fprintf(global.stdmsg, "config %s\n", inifilename ? inifilename : "(none)");
|
||||
}
|
||||
|
||||
//printf("%d source files\n",files.dim);
|
||||
@@ -1349,7 +1456,7 @@ Language changes listed by -transition=id:\n\
|
||||
for (size_t i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = modules[i];
|
||||
m->read(0);
|
||||
m->read(Loc());
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1360,10 +1467,10 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[modi];
|
||||
if (global.params.verbose)
|
||||
printf("parse %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "parse %s\n", m->toChars());
|
||||
if (!Module::rootModule)
|
||||
Module::rootModule = m;
|
||||
m->importedFrom = m;
|
||||
m->importedFrom = m; // m->isRoot() == true
|
||||
if (!global.params.oneobj || modi == 0 || m->isDocFile)
|
||||
m->deleteObjFile();
|
||||
#if ASYNCREAD
|
||||
@@ -1420,7 +1527,7 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("import %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "import %s\n", m->toChars());
|
||||
m->genhdrfile();
|
||||
}
|
||||
}
|
||||
@@ -1432,7 +1539,7 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("importall %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "importall %s\n", m->toChars());
|
||||
m->importAll(NULL);
|
||||
}
|
||||
if (global.errors)
|
||||
@@ -1445,7 +1552,7 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "semantic %s\n", m->toChars());
|
||||
m->semantic();
|
||||
}
|
||||
if (global.errors)
|
||||
@@ -1459,7 +1566,7 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic2 %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "semantic2 %s\n", m->toChars());
|
||||
m->semantic2();
|
||||
}
|
||||
if (global.errors)
|
||||
@@ -1470,12 +1577,11 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic3 %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
|
||||
m->semantic3();
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
if (global.params.useInline)
|
||||
{
|
||||
/* The problem with useArrayBounds and useAssert is that the
|
||||
@@ -1492,22 +1598,28 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = Module::amodules[i];
|
||||
if (global.params.verbose)
|
||||
printf("semantic3 %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
|
||||
m->semantic3();
|
||||
}
|
||||
if (global.errors)
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
Module::runDeferredSemantic3();
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
if (global.params.moduleDeps != NULL)
|
||||
if (global.params.moduleDeps)
|
||||
{
|
||||
assert(global.params.moduleDepsFile != NULL);
|
||||
|
||||
File deps(global.params.moduleDepsFile);
|
||||
OutBuffer* ob = global.params.moduleDeps;
|
||||
deps.setbuffer((void*)ob->data, ob->offset);
|
||||
deps.writev();
|
||||
if (global.params.moduleDepsFile)
|
||||
{
|
||||
File deps(global.params.moduleDepsFile);
|
||||
deps.setbuffer((void*)ob->data, ob->offset);
|
||||
deps.writev();
|
||||
}
|
||||
else
|
||||
printf("%.*s", (int)ob->offset, ob->data);
|
||||
}
|
||||
|
||||
// Scan for functions to inline
|
||||
@@ -1517,7 +1629,7 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("inline scan %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "inline scan %s\n", m->toChars());
|
||||
m->inlineScan();
|
||||
}
|
||||
}
|
||||
@@ -1592,14 +1704,21 @@ Language changes listed by -transition=id:\n\
|
||||
|
||||
if (global.params.oneobj)
|
||||
{
|
||||
if (modules.dim)
|
||||
obj_start(modules[0]->srcfile->toChars());
|
||||
for (size_t i = 0; i < modules.dim; i++)
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("code %s\n", m->toChars());
|
||||
if (i == 0)
|
||||
obj_start(m->srcfile->toChars());
|
||||
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
||||
m->genobjfile(0);
|
||||
if (entrypoint && m == entrypoint->importedFrom)
|
||||
{
|
||||
char v = global.params.verbose;
|
||||
global.params.verbose = 0;
|
||||
entrypoint->genobjfile(0);
|
||||
global.params.verbose = v;
|
||||
}
|
||||
if (!global.errors && global.params.doDocComments)
|
||||
m->gendocfile();
|
||||
}
|
||||
@@ -1614,10 +1733,18 @@ Language changes listed by -transition=id:\n\
|
||||
{
|
||||
m = modules[i];
|
||||
if (global.params.verbose)
|
||||
printf("code %s\n", m->toChars());
|
||||
fprintf(global.stdmsg, "code %s\n", m->toChars());
|
||||
if (global.params.obj)
|
||||
{ obj_start(m->srcfile->toChars());
|
||||
{
|
||||
obj_start(m->srcfile->toChars());
|
||||
m->genobjfile(global.params.multiobj);
|
||||
if (entrypoint && m == entrypoint->importedFrom)
|
||||
{
|
||||
char v = global.params.verbose;
|
||||
global.params.verbose = 0;
|
||||
entrypoint->genobjfile(global.params.multiobj);
|
||||
global.params.verbose = v;
|
||||
}
|
||||
obj_end(library, m->objfile);
|
||||
obj_write_deferred(library);
|
||||
}
|
||||
@@ -1662,8 +1789,7 @@ Language changes listed by -transition=id:\n\
|
||||
*/
|
||||
for (size_t i = 0; i < modules.dim; i++)
|
||||
{
|
||||
Module *m = modules[i];
|
||||
m->deleteObjFile();
|
||||
modules[i]->deleteObjFile();
|
||||
if (global.params.oneobj)
|
||||
break;
|
||||
}
|
||||
@@ -1814,12 +1940,33 @@ Ldone:
|
||||
assert(argc == argv->dim);
|
||||
argv->reserve(argc_left);
|
||||
for (int i = 0; i < argc_left; i++)
|
||||
argv->data[argc++] = (void *)(*pargv)[i];
|
||||
(*argv)[argc++] = (*pargv)[i];
|
||||
|
||||
*pargc = argc;
|
||||
*pargv = argv->tdata();
|
||||
}
|
||||
|
||||
void escapePath(OutBuffer *buf, const char *fname)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
switch (*fname)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case '(':
|
||||
case ')':
|
||||
case '\\':
|
||||
buf->writebyte('\\');
|
||||
default:
|
||||
buf->writebyte(*fname);
|
||||
break;
|
||||
}
|
||||
fname++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Parse command line arguments for -m32 or -m64
|
||||
* to detect the desired architecture.
|
||||
|
||||
+30
-29
@@ -94,10 +94,6 @@ void unittests();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
/* Changes for the GDC compiler by David Friedman */
|
||||
#endif
|
||||
|
||||
#define DMDV1 0
|
||||
#define DMDV2 1 // Version 2.0 features
|
||||
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
|
||||
@@ -137,9 +133,9 @@ void unittests();
|
||||
struct OutBuffer;
|
||||
|
||||
// Can't include arraytypes.h here, need to declare these directly.
|
||||
template <typename TYPE> struct ArrayBase;
|
||||
typedef ArrayBase<struct Identifier> Identifiers;
|
||||
typedef ArrayBase<char> Strings;
|
||||
template <typename TYPE> struct Array;
|
||||
typedef Array<class Identifier> Identifiers;
|
||||
typedef Array<char> Strings;
|
||||
|
||||
#if IN_LLVM
|
||||
enum OUTPUTFLAG
|
||||
@@ -164,6 +160,7 @@ struct Param
|
||||
ubyte symdebug; // insert debug symbolic information
|
||||
bool trace; // insert profiling hooks
|
||||
bool is64bit; // generate 64 bit code
|
||||
bool isLP64; // generate code for LP64
|
||||
bool isLinux; // generate code for linux
|
||||
bool isOSX; // generate code for Mac OSX
|
||||
bool isWindows; // generate code for Windows
|
||||
@@ -185,6 +182,7 @@ struct Param
|
||||
bool optimize; // run optimizer
|
||||
char map; // generate linker .map file
|
||||
char is64bit; // generate 64 bit code
|
||||
char isLP64; // generate code for LP64
|
||||
char isLinux; // generate code for linux
|
||||
char isOSX; // generate code for Mac OSX
|
||||
char isWindows; // generate code for Windows
|
||||
@@ -225,7 +223,6 @@ struct Param
|
||||
bool cov; // generate code coverage data
|
||||
unsigned char covPercent; // 0..100 code coverage percentage required
|
||||
bool nofloat; // code should not pull in floating point support
|
||||
char Dversion; // D version number
|
||||
char ignoreUnsupportedPragmas; // rather than error on them
|
||||
char enforcePropertySyntax;
|
||||
char betterC; // be a "better C" compiler; no dependency on D runtime
|
||||
@@ -256,8 +253,6 @@ struct Param
|
||||
unsigned versionlevel; // version level
|
||||
Strings *versionids; // version identifiers
|
||||
|
||||
bool dump_source;
|
||||
|
||||
Strings *defaultlibnames; // default libraries for non-debug builds
|
||||
Strings *debuglibnames; // default libraries for debug builds
|
||||
|
||||
@@ -322,6 +317,14 @@ typedef unsigned structalign_t;
|
||||
#define STRUCTALIGN_DEFAULT ~0 // magic value means "match whatever the underlying C compiler does"
|
||||
// other values are all powers of 2
|
||||
|
||||
struct Ungag
|
||||
{
|
||||
unsigned oldgag;
|
||||
|
||||
Ungag(unsigned old) : oldgag(old) {}
|
||||
~Ungag();
|
||||
};
|
||||
|
||||
struct Global
|
||||
{
|
||||
const char *mars_ext;
|
||||
@@ -358,6 +361,7 @@ struct Global
|
||||
Param params;
|
||||
unsigned errors; // number of errors reported so far
|
||||
unsigned warnings; // number of warnings reported so far
|
||||
FILE *stdmsg; // where to send verbose messages
|
||||
unsigned gag; // !=0 means gag reporting of errors & warnings
|
||||
unsigned gaggedErrors; // number of errors reported while gagged
|
||||
|
||||
@@ -375,6 +379,12 @@ struct Global
|
||||
*/
|
||||
bool endGagging(unsigned oldGagged);
|
||||
|
||||
/* Increment the error count to record that an error
|
||||
* has occured in the current context. An error message
|
||||
* may or may not have been printed.
|
||||
*/
|
||||
void increaseErrorCount();
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
@@ -391,12 +401,7 @@ extern Global global;
|
||||
#include <complex.h>
|
||||
typedef _Complex long double complex_t;
|
||||
#else
|
||||
#ifndef IN_GCC
|
||||
#include "complex_t.h"
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
//#include "complex.h"//This causes problems with include the c++ <complex> and not the C "complex.h"
|
||||
#endif
|
||||
#include "complex_t.h"
|
||||
#endif
|
||||
|
||||
// Be careful not to care about sign when using dinteger_t
|
||||
@@ -425,17 +430,10 @@ typedef d_uns8 d_char;
|
||||
typedef d_uns16 d_wchar;
|
||||
typedef d_uns32 d_dchar;
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
#else
|
||||
typedef longdouble real_t;
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-complex_t.h"
|
||||
#endif
|
||||
|
||||
struct Module;
|
||||
class Module;
|
||||
|
||||
//typedef unsigned Loc; // file location
|
||||
struct Loc
|
||||
@@ -456,7 +454,9 @@ struct Loc
|
||||
};
|
||||
|
||||
#ifndef GCC_SAFE_DMD
|
||||
#undef TRUE
|
||||
#define TRUE 1
|
||||
#undef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
@@ -508,7 +508,9 @@ void warning(Loc loc, const char *format, ...);
|
||||
void deprecation(Loc loc, const char *format, ...);
|
||||
void error(Loc loc, const char *format, ...);
|
||||
void errorSupplemental(Loc loc, const char *format, ...);
|
||||
extern "C" {
|
||||
void verror(Loc loc, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL, const char *header = "Error: ");
|
||||
}
|
||||
void vwarning(Loc loc, const char *format, va_list);
|
||||
void verrorSupplemental(Loc loc, const char *format, va_list ap);
|
||||
void verrorPrint(Loc loc, const char *header, const char *format, va_list ap, const char *p1 = NULL, const char *p2 = NULL);
|
||||
@@ -530,14 +532,11 @@ int runProgram();
|
||||
const char *inifile(const char *argv0, const char *inifile, const char* envsectionname);
|
||||
#endif
|
||||
void halt();
|
||||
#if !IN_LLVM
|
||||
void util_progress();
|
||||
#endif
|
||||
|
||||
#if !IN_LLVM
|
||||
struct Dsymbol;
|
||||
class Dsymbol;
|
||||
class Library;
|
||||
struct File;
|
||||
class File;
|
||||
void obj_start(char *srcfile);
|
||||
void obj_end(Library *library, File *objfile);
|
||||
void obj_append(Dsymbol *s);
|
||||
@@ -545,5 +544,7 @@ void obj_write_deferred(Library *library);
|
||||
#endif
|
||||
|
||||
const char *importHint(const char *s);
|
||||
/// Little helper function for writting out deps.
|
||||
void escapePath(OutBuffer *buf, const char *fname);
|
||||
|
||||
#endif /* DMD_MARS_H */
|
||||
|
||||
+236
-131
@@ -34,8 +34,11 @@ DsymbolTable *Module::modules;
|
||||
Modules Module::amodules;
|
||||
|
||||
Dsymbols Module::deferred; // deferred Dsymbol's needing semantic() run on them
|
||||
Dsymbols Module::deferred3;
|
||||
unsigned Module::dprogress;
|
||||
|
||||
const char *lookForSourceFile(const char *filename);
|
||||
|
||||
void Module::init()
|
||||
{
|
||||
modules = new DsymbolTable();
|
||||
@@ -59,13 +62,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
||||
needmoduleinfo = 0;
|
||||
selfimports = 0;
|
||||
insearch = 0;
|
||||
searchCacheIdent = NULL;
|
||||
searchCacheSymbol = NULL;
|
||||
searchCacheFlags = 0;
|
||||
semanticstarted = 0;
|
||||
semanticRun = 0;
|
||||
decldefs = NULL;
|
||||
vmoduleinfo = NULL;
|
||||
#if IN_DMD
|
||||
massert = NULL;
|
||||
munittest = NULL;
|
||||
@@ -78,7 +75,6 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
||||
stest = NULL;
|
||||
sfilename = NULL;
|
||||
#endif
|
||||
root = 0;
|
||||
importedFrom = NULL;
|
||||
srcfile = NULL;
|
||||
objfile = NULL;
|
||||
@@ -134,7 +130,6 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
||||
moduleInfoVar = NULL;
|
||||
this->doDocComment = doDocComment;
|
||||
this->doHdrGen = doHdrGen;
|
||||
this->isRoot = false;
|
||||
this->arrayfuncs = 0;
|
||||
#endif
|
||||
}
|
||||
@@ -241,55 +236,23 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
|
||||
m = new Module(filename, ident, 0, 0);
|
||||
m->loc = loc;
|
||||
|
||||
/* Search along global.path for .di file, then .d file.
|
||||
/* Look for the source file
|
||||
*/
|
||||
const char *result = NULL;
|
||||
const char *fdi = FileName::forceExt(filename, global.hdr_ext);
|
||||
const char *fd = FileName::forceExt(filename, global.mars_ext);
|
||||
const char *sdi = fdi;
|
||||
const char *sd = fd;
|
||||
|
||||
if (FileName::exists(sdi))
|
||||
result = sdi;
|
||||
else if (FileName::exists(sd))
|
||||
result = sd;
|
||||
else if (FileName::absolute(filename))
|
||||
;
|
||||
else if (!global.path)
|
||||
;
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < global.path->dim; i++)
|
||||
{
|
||||
const char *p = (*global.path)[i];
|
||||
const char *n = FileName::combine(p, sdi);
|
||||
if (FileName::exists(n))
|
||||
{ result = n;
|
||||
break;
|
||||
}
|
||||
FileName::free(n);
|
||||
n = FileName::combine(p, sd);
|
||||
if (FileName::exists(n))
|
||||
{ result = n;
|
||||
break;
|
||||
}
|
||||
FileName::free(n);
|
||||
}
|
||||
}
|
||||
const char *result = lookForSourceFile(filename);
|
||||
if (result)
|
||||
m->srcfile = new File(result);
|
||||
|
||||
if (global.params.verbose)
|
||||
{
|
||||
printf("import ");
|
||||
fprintf(global.stdmsg, "import ");
|
||||
if (packages)
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (*packages)[i];
|
||||
printf("%s.", pid->toChars());
|
||||
fprintf(global.stdmsg, "%s.", pid->toChars());
|
||||
}
|
||||
}
|
||||
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
|
||||
fprintf(global.stdmsg, "%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
|
||||
}
|
||||
|
||||
if (!m->read(loc))
|
||||
@@ -316,7 +279,15 @@ bool Module::read(Loc loc)
|
||||
}
|
||||
else
|
||||
{
|
||||
error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
|
||||
// if module is not named 'package' but we're trying to read 'package.d', we're looking for a package module
|
||||
bool isPackageMod = (strcmp(toChars(), "package") != 0) &&
|
||||
(strcmp(srcfile->name->name(), "package.d") == 0);
|
||||
|
||||
if (isPackageMod)
|
||||
::error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'",
|
||||
toChars(), srcfile->toChars());
|
||||
else
|
||||
error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
|
||||
}
|
||||
|
||||
if (!global.gag)
|
||||
@@ -422,7 +393,7 @@ void Module::parse()
|
||||
char *srcname = srcfile->name->toChars();
|
||||
//printf("Module::parse(srcname = '%s')\n", srcname);
|
||||
|
||||
unsigned char *buf = srcfile->buffer;
|
||||
utf8_t *buf = srcfile->buffer;
|
||||
size_t buflen = srcfile->len;
|
||||
|
||||
if (buflen >= 2)
|
||||
@@ -472,7 +443,7 @@ void Module::parse()
|
||||
}
|
||||
dbuf.writeByte(0); // add 0 as sentinel for scanner
|
||||
buflen = dbuf.offset - 1; // don't include sentinel in count
|
||||
buf = (unsigned char *) dbuf.extractData();
|
||||
buf = (utf8_t *) dbuf.extractData();
|
||||
}
|
||||
else
|
||||
{ // UTF-16LE (X86)
|
||||
@@ -525,7 +496,7 @@ void Module::parse()
|
||||
}
|
||||
dbuf.writeByte(0); // add 0 as sentinel for scanner
|
||||
buflen = dbuf.offset - 1; // don't include sentinel in count
|
||||
buf = (unsigned char *) dbuf.extractData();
|
||||
buf = (utf8_t *) dbuf.extractData();
|
||||
}
|
||||
}
|
||||
else if (buf[0] == 0xFE && buf[1] == 0xFF)
|
||||
@@ -586,14 +557,6 @@ void Module::parse()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IN_GCC
|
||||
// dump utf-8 encoded source
|
||||
if (global.params.dump_source)
|
||||
{ // %% srcname could contain a path ...
|
||||
d_gcc_dump_source(srcname, "utf-8", buf, buflen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If it starts with the string "Ddoc", then it's a documentation
|
||||
* source file.
|
||||
*/
|
||||
@@ -623,25 +586,36 @@ void Module::parse()
|
||||
srcfile->len = 0;
|
||||
|
||||
md = p.md;
|
||||
numlines = p.loc.linnum;
|
||||
numlines = p.scanloc.linnum;
|
||||
|
||||
/* The symbol table into which the module is to be inserted.
|
||||
*/
|
||||
DsymbolTable *dst;
|
||||
|
||||
if (md)
|
||||
{ this->ident = md->id;
|
||||
{ /* A ModuleDeclaration, md, was provided.
|
||||
* The ModuleDeclaration sets the packages this module appears in, and
|
||||
* the name of this module.
|
||||
*/
|
||||
this->ident = md->id;
|
||||
this->safe = md->safe;
|
||||
Package *ppack = NULL;
|
||||
dst = Package::resolve(md->packages, &this->parent, &ppack);
|
||||
assert(dst);
|
||||
#if 0
|
||||
if (ppack && ppack->isModule())
|
||||
{
|
||||
error(loc, "package name '%s' in file %s conflicts with usage as a module name in file %s",
|
||||
ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars());
|
||||
dst = modules;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = modules;
|
||||
{ /* The name of the module is set to the source file name.
|
||||
* There are no packages.
|
||||
*/
|
||||
dst = modules; // and so this module goes into global module symbol table
|
||||
|
||||
/* Check to see if module name is a valid identifier
|
||||
*/
|
||||
@@ -649,9 +623,40 @@ void Module::parse()
|
||||
error("has non-identifier characters in filename, use module declaration instead");
|
||||
}
|
||||
|
||||
// Update global list of modules
|
||||
if (!dst->insert(this))
|
||||
// Insert module into the symbol table
|
||||
Dsymbol *s = this;
|
||||
bool isPackageMod = strcmp(srcfile->name->name(), "package.d") == 0;
|
||||
if (isPackageMod)
|
||||
{
|
||||
/* If the source tree is as follows:
|
||||
* pkg/
|
||||
* +- package.d
|
||||
* +- common.d
|
||||
* the 'pkg' will be incorporated to the internal package tree in two ways:
|
||||
* import pkg;
|
||||
* and:
|
||||
* import pkg.common;
|
||||
*
|
||||
* If both are used in one compilation, 'pkg' as a module (== pkg/package.d)
|
||||
* and a package name 'pkg' will conflict each other.
|
||||
*
|
||||
* To avoid the conflict:
|
||||
* 1. If preceding package name insertion had occurred by Package::resolve,
|
||||
* later package.d loading will change Package::isPkgMod to PKGmodule and set Package::mod.
|
||||
* 2. Otherwise, 'package.d' wrapped by 'Package' is inserted to the internal tree in here.
|
||||
*/
|
||||
Package *p = new Package(ident);
|
||||
p->parent = this->parent;
|
||||
p->isPkgMod = PKGmodule;
|
||||
p->mod = this;
|
||||
p->symtab = new DsymbolTable();
|
||||
s = p;
|
||||
}
|
||||
if (!dst->insert(s))
|
||||
{
|
||||
/* It conflicts with a name that is already in the symbol table.
|
||||
* Figure out what went wrong, and issue error message.
|
||||
*/
|
||||
Dsymbol *prev = dst->lookup(ident);
|
||||
assert(prev);
|
||||
Module *mprev = prev->isModule();
|
||||
@@ -668,12 +673,22 @@ void Module::parse()
|
||||
{
|
||||
Package *pkg = prev->isPackage();
|
||||
assert(pkg);
|
||||
error(pkg->loc, "from file %s conflicts with package name %s",
|
||||
srcname, pkg->toChars());
|
||||
if (pkg->isPkgMod == PKGunknown && isPackageMod)
|
||||
{
|
||||
/* If the previous inserted Package is not yet determined as package.d,
|
||||
* link it to the actual module.
|
||||
*/
|
||||
pkg->isPkgMod = PKGmodule;
|
||||
pkg->mod = this;
|
||||
}
|
||||
else
|
||||
error(pkg->loc, "from file %s conflicts with package name %s",
|
||||
srcname, pkg->toChars());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add to global array of all modules
|
||||
amodules.push(this);
|
||||
}
|
||||
}
|
||||
@@ -743,18 +758,18 @@ void Module::importAll(Scope *prevsc)
|
||||
|
||||
void Module::semantic()
|
||||
{
|
||||
if (semanticstarted)
|
||||
if (semanticRun != PASSinit)
|
||||
return;
|
||||
|
||||
//printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
|
||||
semanticstarted = 1;
|
||||
semanticRun = PASSsemantic;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
// gets imported, it is unaffected by context.
|
||||
Scope *sc = scope; // see if already got one from importAll()
|
||||
if (!sc)
|
||||
{ printf("test2\n");
|
||||
{
|
||||
Scope::createGlobal(this); // create root scope
|
||||
}
|
||||
|
||||
@@ -786,14 +801,6 @@ void Module::semantic()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Do semantic() on members that don't depend on others
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
|
||||
//printf("\tModule('%s'): '%s'.semantic0()\n", toChars(), s->toChars());
|
||||
s->semantic0(sc);
|
||||
}
|
||||
|
||||
// Pass 1 semantic routines: do public side of the definition
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
@@ -807,7 +814,7 @@ void Module::semantic()
|
||||
{ sc = sc->pop();
|
||||
sc->pop(); // 2 pops because Scope::createGlobal() created 2
|
||||
}
|
||||
semanticRun = semanticstarted;
|
||||
semanticRun = PASSsemanticdone;
|
||||
//printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
|
||||
}
|
||||
|
||||
@@ -824,12 +831,9 @@ void Module::semantic2()
|
||||
return;
|
||||
}
|
||||
//printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
|
||||
if (semanticRun == 0) // semantic() not completed yet - could be recursive call
|
||||
if (semanticRun != PASSsemanticdone) // semantic() not completed yet - could be recursive call
|
||||
return;
|
||||
if (semanticstarted >= 2)
|
||||
return;
|
||||
assert(semanticstarted == 1);
|
||||
semanticstarted = 2;
|
||||
semanticRun = PASSsemantic2;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
@@ -847,17 +851,16 @@ void Module::semantic2()
|
||||
|
||||
sc = sc->pop();
|
||||
sc->pop();
|
||||
semanticRun = semanticstarted;
|
||||
semanticRun = PASSsemantic2done;
|
||||
//printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
|
||||
}
|
||||
|
||||
void Module::semantic3()
|
||||
{
|
||||
//printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
|
||||
if (semanticstarted >= 3)
|
||||
if (semanticRun != PASSsemantic2done)
|
||||
return;
|
||||
assert(semanticstarted == 2);
|
||||
semanticstarted = 3;
|
||||
semanticRun = PASSsemantic3;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
@@ -876,15 +879,14 @@ void Module::semantic3()
|
||||
|
||||
sc = sc->pop();
|
||||
sc->pop();
|
||||
semanticRun = semanticstarted;
|
||||
semanticRun = PASSsemantic3done;
|
||||
}
|
||||
|
||||
void Module::inlineScan()
|
||||
{
|
||||
if (semanticstarted >= 4)
|
||||
if (semanticRun != PASSsemantic3done)
|
||||
return;
|
||||
assert(semanticstarted == 3);
|
||||
semanticstarted = 4;
|
||||
semanticRun = PASSinline;
|
||||
|
||||
// Note that modules get their own scope, from scratch.
|
||||
// This is so regardless of where in the syntax a module
|
||||
@@ -894,11 +896,11 @@ void Module::inlineScan()
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
//if (global.params.verbose)
|
||||
//printf("inline scan symbol %s\n", s->toChars());
|
||||
//fprintf(global.stdmsg, "inline scan symbol %s\n", s->toChars());
|
||||
|
||||
s->inlineScan();
|
||||
}
|
||||
semanticRun = semanticstarted;
|
||||
semanticRun = PASSinlinedone;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
@@ -951,38 +953,15 @@ Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
|
||||
Dsymbol *s;
|
||||
if (insearch)
|
||||
s = NULL;
|
||||
else if (searchCacheIdent == ident && searchCacheFlags == flags)
|
||||
{
|
||||
s = searchCacheSymbol;
|
||||
//printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", toChars(), ident->toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol->toChars() : "null");
|
||||
}
|
||||
else
|
||||
{
|
||||
insearch = 1;
|
||||
s = ScopeDsymbol::search(loc, ident, flags);
|
||||
insearch = 0;
|
||||
|
||||
searchCacheIdent = ident;
|
||||
searchCacheSymbol = s;
|
||||
searchCacheFlags = flags;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Dsymbol *Module::symtabInsert(Dsymbol *s)
|
||||
{
|
||||
searchCacheIdent = NULL; // symbol is inserted, so invalidate cache
|
||||
return Package::symtabInsert(s);
|
||||
}
|
||||
|
||||
void Module::clearCache()
|
||||
{
|
||||
for (size_t i = 0; i < amodules.dim; i++)
|
||||
{ Module *m = amodules[i];
|
||||
m->searchCacheIdent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Can't run semantic on s now, try again later.
|
||||
*/
|
||||
@@ -1057,6 +1036,33 @@ void Module::runDeferredSemantic()
|
||||
//printf("-Module::runDeferredSemantic(), len = %d\n", deferred.dim);
|
||||
}
|
||||
|
||||
void Module::addDeferredSemantic3(Dsymbol *s)
|
||||
{
|
||||
// Don't add it if it is already there
|
||||
for (size_t i = 0; i < deferred3.dim; i++)
|
||||
{
|
||||
Dsymbol *sd = deferred3[i];
|
||||
if (sd == s)
|
||||
return;
|
||||
}
|
||||
deferred3.push(s);
|
||||
}
|
||||
|
||||
void Module::runDeferredSemantic3()
|
||||
{
|
||||
Dsymbols *a = &Module::deferred3;
|
||||
for (size_t i = 0; i < a->dim; i++)
|
||||
{
|
||||
Dsymbol *s = (*a)[i];
|
||||
//printf("[%d] %s semantic3a\n", i, s->toPrettyChars());
|
||||
|
||||
s->semantic3(NULL);
|
||||
|
||||
if (global.errors)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Recursively look at every module this module imports,
|
||||
* return TRUE if it imports m.
|
||||
@@ -1116,8 +1122,9 @@ int Module::selfImports()
|
||||
|
||||
/* =========================== ModuleDeclaration ===================== */
|
||||
|
||||
ModuleDeclaration::ModuleDeclaration(Identifiers *packages, Identifier *id, bool safe)
|
||||
ModuleDeclaration::ModuleDeclaration(Loc loc, Identifiers *packages, Identifier *id, bool safe)
|
||||
{
|
||||
this->loc = loc;
|
||||
this->packages = packages;
|
||||
this->id = id;
|
||||
this->safe = safe;
|
||||
@@ -1146,6 +1153,8 @@ char *ModuleDeclaration::toChars()
|
||||
Package::Package(Identifier *ident)
|
||||
: ScopeDsymbol(ident)
|
||||
{
|
||||
this->isPkgMod = PKGunknown;
|
||||
this->mod = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1154,6 +1163,15 @@ const char *Package::kind()
|
||||
return "package";
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Input:
|
||||
* packages[] the pkg1.pkg2 of pkg1.pkg2.mod
|
||||
* Returns:
|
||||
* the symbol table that mod should be inserted into
|
||||
* Output:
|
||||
* *pparent the rightmost package, i.e. pkg2, or NULL if no packages
|
||||
* *ppkg the leftmost package, i.e. pkg1, or NULL if no packages
|
||||
*/
|
||||
|
||||
DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package **ppkg)
|
||||
{
|
||||
@@ -1168,39 +1186,126 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
|
||||
{
|
||||
for (size_t i = 0; i < packages->dim; i++)
|
||||
{ Identifier *pid = (*packages)[i];
|
||||
Dsymbol *p;
|
||||
|
||||
p = dst->lookup(pid);
|
||||
Package *pkg;
|
||||
Dsymbol *p = dst->lookup(pid);
|
||||
if (!p)
|
||||
{
|
||||
p = new Package(pid);
|
||||
dst->insert(p);
|
||||
p->parent = parent;
|
||||
((ScopeDsymbol *)p)->symtab = new DsymbolTable();
|
||||
pkg = new Package(pid);
|
||||
dst->insert(pkg);
|
||||
pkg->parent = parent;
|
||||
pkg->symtab = new DsymbolTable();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(p->isPackage());
|
||||
pkg = p->isPackage();
|
||||
assert(pkg);
|
||||
// It might already be a module, not a package, but that needs
|
||||
// to be checked at a higher level, where a nice error message
|
||||
// can be generated.
|
||||
// dot net needs modules and packages with same name
|
||||
|
||||
// But we still need a symbol table for it
|
||||
if (!pkg->symtab)
|
||||
pkg->symtab = new DsymbolTable();
|
||||
}
|
||||
parent = p;
|
||||
dst = ((Package *)p)->symtab;
|
||||
parent = pkg;
|
||||
dst = pkg->symtab;
|
||||
if (ppkg && !*ppkg)
|
||||
*ppkg = (Package *)p;
|
||||
if (p->isModule())
|
||||
*ppkg = pkg;
|
||||
#if 0
|
||||
if (pkg->isModule())
|
||||
{ // Return the module so that a nice error message can be generated
|
||||
if (ppkg)
|
||||
*ppkg = (Package *)p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pparent)
|
||||
{
|
||||
*pparent = parent;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (pparent)
|
||||
*pparent = parent;
|
||||
return dst;
|
||||
}
|
||||
|
||||
Dsymbol *Package::search(Loc loc, Identifier *ident, int flags)
|
||||
{
|
||||
if (!isModule() && mod)
|
||||
{
|
||||
// Prefer full package name.
|
||||
Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
|
||||
if (s)
|
||||
return s;
|
||||
//printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
|
||||
return mod->search(loc, ident, flags);
|
||||
}
|
||||
|
||||
return ScopeDsymbol::search(loc, ident, flags);
|
||||
}
|
||||
|
||||
/* =========================== ===================== */
|
||||
|
||||
/********************************************
|
||||
* Look for the source file if it's different from filename.
|
||||
* Look for .di, .d, directory, and along global.path.
|
||||
* Does not open the file.
|
||||
* Input:
|
||||
* filename as supplied by the user
|
||||
* global.path
|
||||
* Returns:
|
||||
* NULL if it's not different from filename.
|
||||
*/
|
||||
|
||||
const char *lookForSourceFile(const char *filename)
|
||||
{
|
||||
|
||||
/* Search along global.path for .di file, then .d file.
|
||||
*/
|
||||
|
||||
const char *sdi = FileName::forceExt(filename, global.hdr_ext);
|
||||
if (FileName::exists(sdi) == 1)
|
||||
return sdi;
|
||||
|
||||
const char *sd = FileName::forceExt(filename, global.mars_ext);
|
||||
if (FileName::exists(sd) == 1)
|
||||
return sd;
|
||||
|
||||
if (FileName::exists(filename) == 2)
|
||||
{
|
||||
/* The filename exists and it's a directory.
|
||||
* Therefore, the result should be: filename/package.d
|
||||
*/
|
||||
return FileName::combine(filename, "package.d");
|
||||
}
|
||||
|
||||
if (FileName::absolute(filename))
|
||||
return NULL;
|
||||
|
||||
if (!global.path)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = 0; i < global.path->dim; i++)
|
||||
{
|
||||
const char *p = (*global.path)[i];
|
||||
|
||||
const char *n = FileName::combine(p, sdi);
|
||||
if (FileName::exists(n) == 1)
|
||||
return n;
|
||||
FileName::free(n);
|
||||
|
||||
n = FileName::combine(p, sd);
|
||||
if (FileName::exists(n) == 1)
|
||||
return n;
|
||||
FileName::free(n);
|
||||
|
||||
const char *b = FileName::removeExt(filename);
|
||||
n = FileName::combine(p, b);
|
||||
FileName::free(b);
|
||||
if (FileName::exists(n) == 2)
|
||||
return FileName::combine(n, "package.d");
|
||||
FileName::free(n);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+31
-26
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -18,12 +18,11 @@
|
||||
#include "root.h"
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct ModuleInfoDeclaration;
|
||||
struct ClassDeclaration;
|
||||
class ClassDeclaration;
|
||||
struct ModuleDeclaration;
|
||||
struct Macro;
|
||||
struct Escape;
|
||||
struct VarDeclaration;
|
||||
class VarDeclaration;
|
||||
class Library;
|
||||
|
||||
// Back end
|
||||
@@ -39,14 +38,25 @@ namespace llvm {
|
||||
#else
|
||||
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node elem;
|
||||
typedef union tree_node elem;
|
||||
#else
|
||||
struct elem;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct Package : ScopeDsymbol
|
||||
enum PKG
|
||||
{
|
||||
PKGunknown, // not yet determined whether it's a package.d or not
|
||||
PKGmodule, // already determined that's an actual package.d
|
||||
PKGpackage, // already determined that's an actual package
|
||||
};
|
||||
|
||||
class Package : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
PKG isPkgMod;
|
||||
Module *mod; // != NULL if isPkgMod == PKGmodule
|
||||
|
||||
Package(Identifier *ident);
|
||||
const char *kind();
|
||||
|
||||
@@ -54,15 +64,18 @@ struct Package : ScopeDsymbol
|
||||
|
||||
Package *isPackage() { return this; }
|
||||
|
||||
virtual void semantic(Scope *sc) { }
|
||||
virtual void semantic(Scope *) { }
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
};
|
||||
|
||||
struct Module : Package
|
||||
class Module : public Package
|
||||
{
|
||||
public:
|
||||
static Module *rootModule;
|
||||
static DsymbolTable *modules; // symbol table of all modules
|
||||
static Modules amodules; // array of all modules
|
||||
static Dsymbols deferred; // deferred Dsymbol's needing semantic() run on them
|
||||
static Dsymbols deferred3; // deferred Dsymbol's needing semantic3() run on them
|
||||
static unsigned dprogress; // progress resolving the deferred list
|
||||
static void init();
|
||||
|
||||
@@ -85,15 +98,7 @@ struct Module : Package
|
||||
int selfImports(); // returns !=0 if module imports itself
|
||||
|
||||
int insearch;
|
||||
Identifier *searchCacheIdent;
|
||||
Dsymbol *searchCacheSymbol; // cached value of search
|
||||
int searchCacheFlags; // cached flags
|
||||
|
||||
int semanticstarted; // has semantic() been started?
|
||||
int semanticRun; // has semantic() been done?
|
||||
int root; // != 0 if this is a 'root' module,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
Module *importedFrom; // module from command line we're imported from,
|
||||
// i.e. a module that will be taken all the
|
||||
// way to an object file
|
||||
@@ -102,8 +107,6 @@ struct Module : Package
|
||||
|
||||
Modules aimports; // all imported modules
|
||||
|
||||
ModuleInfoDeclaration *vmoduleinfo;
|
||||
|
||||
unsigned debuglevel; // debug level
|
||||
Strings *debugids; // debug identifiers
|
||||
Strings *debugidsNot; // forward referenced debug identifiers
|
||||
@@ -114,7 +117,7 @@ struct Module : Package
|
||||
|
||||
Macro *macrotable; // document comment macros
|
||||
Escape *escapetable; // document comment escapes
|
||||
bool safe; // TRUE if module is marked as 'safe'
|
||||
bool safe; // true if module is marked as 'safe'
|
||||
|
||||
size_t nameoffset; // offset of module name from start of ModuleInfo
|
||||
size_t namelen; // length of module name in characters
|
||||
@@ -154,13 +157,17 @@ struct Module : Package
|
||||
void gendocfile();
|
||||
int needModuleInfo();
|
||||
Dsymbol *search(Loc loc, Identifier *ident, int flags);
|
||||
Dsymbol *symtabInsert(Dsymbol *s);
|
||||
void deleteObjFile();
|
||||
void addDeferredSemantic(Dsymbol *s);
|
||||
static void addDeferredSemantic(Dsymbol *s);
|
||||
static void runDeferredSemantic();
|
||||
static void clearCache();
|
||||
static void addDeferredSemantic3(Dsymbol *s);
|
||||
static void runDeferredSemantic3();
|
||||
int imports(Module *m);
|
||||
|
||||
bool isRoot() { return this->importedFrom == this; }
|
||||
// true if the module source file is directly
|
||||
// listed in command line.
|
||||
|
||||
// Back end
|
||||
#if IN_DMD
|
||||
int doppelganger; // sub-module
|
||||
@@ -186,7 +193,6 @@ struct Module : Package
|
||||
Symbol *toModuleArray(); // get module array bounds function
|
||||
|
||||
|
||||
static Symbol *gencritsec();
|
||||
elem *toEfilename();
|
||||
|
||||
Symbol *toSymbol();
|
||||
@@ -206,19 +212,18 @@ struct Module : Package
|
||||
|
||||
// array ops emitted in this module already
|
||||
AA *arrayfuncs;
|
||||
|
||||
bool isRoot;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct ModuleDeclaration
|
||||
{
|
||||
Loc loc;
|
||||
Identifier *id;
|
||||
Identifiers *packages; // array of Identifier's representing packages
|
||||
bool safe;
|
||||
|
||||
ModuleDeclaration(Identifiers *packages, Identifier *id, bool safe);
|
||||
ModuleDeclaration(Loc loc, Identifiers *packages, Identifier *id, bool safe);
|
||||
|
||||
char *toChars();
|
||||
};
|
||||
|
||||
+615
-493
File diff suppressed because it is too large
Load Diff
+98
-68
@@ -28,29 +28,28 @@ class IrType;
|
||||
#endif
|
||||
|
||||
struct Scope;
|
||||
struct Identifier;
|
||||
struct Expression;
|
||||
struct StructDeclaration;
|
||||
struct ClassDeclaration;
|
||||
struct VarDeclaration;
|
||||
struct EnumDeclaration;
|
||||
struct TypedefDeclaration;
|
||||
struct TypeInfoDeclaration;
|
||||
struct Dsymbol;
|
||||
struct TemplateInstance;
|
||||
class Identifier;
|
||||
class Expression;
|
||||
class StructDeclaration;
|
||||
class ClassDeclaration;
|
||||
class VarDeclaration;
|
||||
class EnumDeclaration;
|
||||
class TypedefDeclaration;
|
||||
class TypeInfoDeclaration;
|
||||
class Dsymbol;
|
||||
class TemplateInstance;
|
||||
struct CppMangleState;
|
||||
struct TemplateDeclaration;
|
||||
class TemplateDeclaration;
|
||||
struct JsonOut;
|
||||
enum LINK;
|
||||
|
||||
struct TypeBasic;
|
||||
class TypeBasic;
|
||||
struct HdrGenState;
|
||||
struct Parameter;
|
||||
class Parameter;
|
||||
|
||||
// Back end
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node TYPE;
|
||||
typedef TYPE type;
|
||||
typedef union tree_node type;
|
||||
#elif IN_LLVM
|
||||
#else
|
||||
typedef struct TYPE type;
|
||||
@@ -60,7 +59,7 @@ typedef struct TYPE type;
|
||||
struct Symbol;
|
||||
#endif
|
||||
|
||||
struct TypeTuple;
|
||||
class TypeTuple;
|
||||
|
||||
enum ENUMTY
|
||||
{
|
||||
@@ -131,13 +130,14 @@ extern int Tptrdiff_t;
|
||||
#define MODwild 8 // type is wild
|
||||
#define MODmutable 0x10 // type is mutable (only used in wildcard matching)
|
||||
|
||||
struct Type : Object
|
||||
class Type : public RootObject
|
||||
{
|
||||
public:
|
||||
TY ty;
|
||||
unsigned char mod; // modifiers MODxxxx
|
||||
char *deco;
|
||||
|
||||
/* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc.
|
||||
/* These are cached values that are lazily evaluated by constOf(), immutableOf(), etc.
|
||||
* They should not be referenced by anybody but mtype.c.
|
||||
* They can be NULL if not lazily evaluated yet.
|
||||
* Note that there is no "shared immutable", because that is just immutable
|
||||
@@ -202,7 +202,7 @@ struct Type : Object
|
||||
static Type *thash_t; // matches hash_t alias
|
||||
static Type *tindex; // array/ptr index
|
||||
|
||||
static ClassDeclaration *typeinfo;
|
||||
static ClassDeclaration *dtypeinfo;
|
||||
static ClassDeclaration *typeinfoclass;
|
||||
static ClassDeclaration *typeinfointerface;
|
||||
static ClassDeclaration *typeinfostruct;
|
||||
@@ -240,8 +240,9 @@ struct Type : Object
|
||||
|
||||
Type(TY ty);
|
||||
virtual const char *kind();
|
||||
Type *copy();
|
||||
virtual Type *syntaxCopy();
|
||||
int equals(Object *o);
|
||||
bool equals(RootObject *o);
|
||||
int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
|
||||
int covariant(Type *t, StorageClass *pstc = NULL);
|
||||
char *toChars();
|
||||
@@ -288,7 +289,7 @@ struct Type : Object
|
||||
int isNaked() { return mod == 0; }
|
||||
Type *nullAttributes();
|
||||
Type *constOf();
|
||||
Type *invariantOf();
|
||||
Type *immutableOf();
|
||||
Type *mutableOf();
|
||||
Type *sharedOf();
|
||||
Type *sharedConstOf();
|
||||
@@ -319,7 +320,7 @@ struct Type : Object
|
||||
virtual MATCH implicitConvTo(Type *to);
|
||||
virtual MATCH constConv(Type *to);
|
||||
virtual unsigned wildConvTo(Type *tprm);
|
||||
Type *substWildTo(unsigned mod);
|
||||
virtual Type *substWildTo(unsigned mod);
|
||||
virtual Type *toHeadMutable();
|
||||
virtual ClassDeclaration *isClassHandle();
|
||||
virtual Expression *getProperty(Loc loc, Identifier *ident, int flag);
|
||||
@@ -335,7 +336,7 @@ struct Type : Object
|
||||
#endif
|
||||
Identifier *getTypeInfoIdent(int internal);
|
||||
virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
|
||||
virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
Expression *getInternalTypeInfo(Scope *sc);
|
||||
Expression *getTypeInfo(Scope *sc);
|
||||
virtual TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
@@ -346,6 +347,7 @@ struct Type : Object
|
||||
virtual int hasPointers();
|
||||
virtual TypeTuple *toArgTypes();
|
||||
virtual Type *nextOf();
|
||||
Type *baseElemOf();
|
||||
uinteger_t sizemask();
|
||||
virtual int needsDestruction();
|
||||
virtual bool needsNested();
|
||||
@@ -370,8 +372,9 @@ struct Type : Object
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeError : Type
|
||||
class TypeError : public Type
|
||||
{
|
||||
public:
|
||||
TypeError();
|
||||
Type *syntaxCopy();
|
||||
|
||||
@@ -385,8 +388,9 @@ struct TypeError : Type
|
||||
TypeTuple *toArgTypes();
|
||||
};
|
||||
|
||||
struct TypeNext : Type
|
||||
class TypeNext : public Type
|
||||
{
|
||||
public:
|
||||
Type *next;
|
||||
|
||||
TypeNext(TY ty, Type *next);
|
||||
@@ -407,8 +411,9 @@ struct TypeNext : Type
|
||||
void transitive();
|
||||
};
|
||||
|
||||
struct TypeBasic : Type
|
||||
class TypeBasic : public Type
|
||||
{
|
||||
public:
|
||||
const char *dstring;
|
||||
unsigned flags;
|
||||
|
||||
@@ -444,8 +449,9 @@ struct TypeBasic : Type
|
||||
TypeBasic *isTypeBasic();
|
||||
};
|
||||
|
||||
struct TypeVector : Type
|
||||
class TypeVector : public Type
|
||||
{
|
||||
public:
|
||||
Type *basetype;
|
||||
|
||||
TypeVector(Loc loc, Type *basetype);
|
||||
@@ -461,6 +467,7 @@ struct TypeVector : Type
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toJson(JsonOut *json);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
|
||||
Type *reliesOnTident(TemplateParameters *tparams);
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
@@ -471,9 +478,7 @@ struct TypeVector : Type
|
||||
int checkBoolean();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
Expression *defaultInit(Loc loc);
|
||||
#if IN_LLVM
|
||||
Expression *defaultInitLiteral(Loc loc);
|
||||
#endif
|
||||
TypeBasic *elementType();
|
||||
int isZeroInit(Loc loc);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
@@ -484,15 +489,17 @@ struct TypeVector : Type
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeArray : TypeNext
|
||||
class TypeArray : public TypeNext
|
||||
{
|
||||
public:
|
||||
TypeArray(TY ty, Type *next);
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
|
||||
};
|
||||
|
||||
// Static array, one with a fixed dimension
|
||||
struct TypeSArray : TypeArray
|
||||
class TypeSArray : public TypeArray
|
||||
{
|
||||
public:
|
||||
Expression *dim;
|
||||
|
||||
TypeSArray(Type *t, Expression *dim);
|
||||
@@ -501,7 +508,7 @@ struct TypeSArray : TypeArray
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
@@ -529,6 +536,8 @@ struct TypeSArray : TypeArray
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
|
||||
static Type *makeType(Loc loc, Type *tn, dinteger_t dim);
|
||||
|
||||
#if IN_DMD
|
||||
type *toCtype();
|
||||
type *toCParamtype();
|
||||
@@ -536,15 +545,16 @@ struct TypeSArray : TypeArray
|
||||
};
|
||||
|
||||
// Dynamic array, no dimension
|
||||
struct TypeDArray : TypeArray
|
||||
class TypeDArray : public TypeArray
|
||||
{
|
||||
public:
|
||||
TypeDArray(Type *t);
|
||||
const char *kind();
|
||||
Type *syntaxCopy();
|
||||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
@@ -568,8 +578,9 @@ struct TypeDArray : TypeArray
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeAArray : TypeArray
|
||||
class TypeAArray : public TypeArray
|
||||
{
|
||||
public:
|
||||
Type *index; // key type
|
||||
Loc loc;
|
||||
Scope *sc;
|
||||
@@ -582,7 +593,7 @@ struct TypeAArray : TypeArray
|
||||
d_uns64 size(Loc loc);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
StructDeclaration *getImpl();
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
@@ -610,8 +621,9 @@ struct TypeAArray : TypeArray
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypePointer : TypeNext
|
||||
class TypePointer : public TypeNext
|
||||
{
|
||||
public:
|
||||
TypePointer(Type *t);
|
||||
const char *kind();
|
||||
Type *syntaxCopy();
|
||||
@@ -636,8 +648,9 @@ struct TypePointer : TypeNext
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeReference : TypeNext
|
||||
class TypeReference : public TypeNext
|
||||
{
|
||||
public:
|
||||
TypeReference(Type *t);
|
||||
const char *kind();
|
||||
Type *syntaxCopy();
|
||||
@@ -676,8 +689,9 @@ enum PURE
|
||||
PUREfwdref = 4, // it's pure, but not known which level yet
|
||||
};
|
||||
|
||||
struct TypeFunction : TypeNext
|
||||
class TypeFunction : public TypeNext
|
||||
{
|
||||
public:
|
||||
// .next is the return type
|
||||
|
||||
Parameters *parameters; // function parameters
|
||||
@@ -686,17 +700,16 @@ struct TypeFunction : TypeNext
|
||||
bool isnothrow; // true: nothrow
|
||||
bool isproperty; // can be called without parentheses
|
||||
bool isref; // true: returns a reference
|
||||
enum LINK linkage; // calling convention
|
||||
enum TRUST trust; // level of trust
|
||||
enum PURE purity; // PURExxxx
|
||||
LINK linkage; // calling convention
|
||||
TRUST trust; // level of trust
|
||||
PURE purity; // PURExxxx
|
||||
bool iswild; // is inout function
|
||||
Expressions *fargs; // function arguments
|
||||
|
||||
int inuse;
|
||||
|
||||
TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc = 0);
|
||||
TypeFunction(Parameters *parameters, Type *treturn, int varargs, LINK linkage, StorageClass stc = 0);
|
||||
const char *kind();
|
||||
TypeFunction *copy();
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void purityLevel();
|
||||
@@ -716,12 +729,13 @@ struct TypeFunction : TypeNext
|
||||
bool parameterEscapes(Parameter *p);
|
||||
Type *addStorageClass(StorageClass stc);
|
||||
|
||||
Type *substWildTo(unsigned mod);
|
||||
MATCH callMatch(Type *tthis, Expressions *toargs, int flag = 0);
|
||||
#if IN_DMD
|
||||
type *toCtype();
|
||||
#endif
|
||||
|
||||
enum RET retStyle();
|
||||
RET retStyle();
|
||||
|
||||
#if IN_DMD
|
||||
unsigned totym();
|
||||
@@ -734,8 +748,9 @@ struct TypeFunction : TypeNext
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeDelegate : TypeNext
|
||||
class TypeDelegate : public TypeNext
|
||||
{
|
||||
public:
|
||||
// .next is a TypeFunction
|
||||
|
||||
TypeDelegate(Type *t);
|
||||
@@ -767,8 +782,9 @@ struct TypeDelegate : TypeNext
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeQualified : Type
|
||||
class TypeQualified : public Type
|
||||
{
|
||||
public:
|
||||
Loc loc;
|
||||
Objects idents; // array of Identifier and TypeInstance,
|
||||
// representing ident.ident!tiargs.ident. ... etc.
|
||||
@@ -781,11 +797,12 @@ struct TypeQualified : Type
|
||||
void toJson(JsonOut *json);
|
||||
d_uns64 size(Loc loc);
|
||||
void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
|
||||
Expression **pe, Type **pt, Dsymbol **ps);
|
||||
Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
};
|
||||
|
||||
struct TypeIdentifier : TypeQualified
|
||||
class TypeIdentifier : public TypeQualified
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution
|
||||
|
||||
@@ -796,7 +813,7 @@ struct TypeIdentifier : TypeQualified
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
|
||||
@@ -806,8 +823,9 @@ struct TypeIdentifier : TypeQualified
|
||||
|
||||
/* Similar to TypeIdentifier, but with a TemplateInstance as the root
|
||||
*/
|
||||
struct TypeInstance : TypeQualified
|
||||
class TypeInstance : public TypeQualified
|
||||
{
|
||||
public:
|
||||
TemplateInstance *tempinst;
|
||||
|
||||
TypeInstance(Loc loc, TemplateInstance *tempinst);
|
||||
@@ -817,7 +835,7 @@ struct TypeInstance : TypeQualified
|
||||
//void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
Type *reliesOnTident(TemplateParameters *tparams = NULL);
|
||||
@@ -825,8 +843,9 @@ struct TypeInstance : TypeQualified
|
||||
Expression *toExpression();
|
||||
};
|
||||
|
||||
struct TypeTypeof : TypeQualified
|
||||
class TypeTypeof : public TypeQualified
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
int inuse;
|
||||
|
||||
@@ -836,18 +855,19 @@ struct TypeTypeof : TypeQualified
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
d_uns64 size(Loc loc);
|
||||
};
|
||||
|
||||
struct TypeReturn : TypeQualified
|
||||
class TypeReturn : public TypeQualified
|
||||
{
|
||||
public:
|
||||
TypeReturn(Loc loc);
|
||||
const char *kind();
|
||||
Type *syntaxCopy();
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
@@ -863,10 +883,11 @@ enum AliasThisRec
|
||||
RECtracing = 0x4, // mark in progress of implicitConvTo/wildConvTo
|
||||
};
|
||||
|
||||
struct TypeStruct : Type
|
||||
class TypeStruct : public Type
|
||||
{
|
||||
public:
|
||||
StructDeclaration *sym;
|
||||
enum AliasThisRec att;
|
||||
AliasThisRec att;
|
||||
|
||||
TypeStruct(StructDeclaration *sym);
|
||||
const char *kind();
|
||||
@@ -914,8 +935,9 @@ struct TypeStruct : Type
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeEnum : Type
|
||||
class TypeEnum : public Type
|
||||
{
|
||||
public:
|
||||
EnumDeclaration *sym;
|
||||
|
||||
TypeEnum(EnumDeclaration *sym);
|
||||
@@ -939,6 +961,7 @@ struct TypeEnum : Type
|
||||
int isscalar();
|
||||
int isunsigned();
|
||||
int checkBoolean();
|
||||
int isString();
|
||||
int isAssignable();
|
||||
int needsDestruction();
|
||||
bool needsNested();
|
||||
@@ -951,6 +974,7 @@ struct TypeEnum : Type
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
Type *nextOf();
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
@@ -960,8 +984,9 @@ struct TypeEnum : Type
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeTypedef : Type
|
||||
class TypeTypedef : public Type
|
||||
{
|
||||
public:
|
||||
TypedefDeclaration *sym;
|
||||
|
||||
TypeTypedef(TypedefDeclaration *sym);
|
||||
@@ -1014,10 +1039,11 @@ struct TypeTypedef : Type
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeClass : Type
|
||||
class TypeClass : public Type
|
||||
{
|
||||
public:
|
||||
ClassDeclaration *sym;
|
||||
enum AliasThisRec att;
|
||||
AliasThisRec att;
|
||||
|
||||
TypeClass(ClassDeclaration *sym);
|
||||
const char *kind();
|
||||
@@ -1056,8 +1082,9 @@ struct TypeClass : Type
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TypeTuple : Type
|
||||
class TypeTuple : public Type
|
||||
{
|
||||
public:
|
||||
Parameters *arguments; // types making up the tuple
|
||||
|
||||
TypeTuple(Parameters *arguments);
|
||||
@@ -1068,7 +1095,7 @@ struct TypeTuple : Type
|
||||
const char *kind();
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
int equals(Object *o);
|
||||
bool equals(RootObject *o);
|
||||
Type *reliesOnTident(TemplateParameters *tparams = NULL);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toDecoBuffer(OutBuffer *buf, int flag);
|
||||
@@ -1078,8 +1105,9 @@ struct TypeTuple : Type
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
};
|
||||
|
||||
struct TypeSlice : TypeNext
|
||||
class TypeSlice : public TypeNext
|
||||
{
|
||||
public:
|
||||
Expression *lwr;
|
||||
Expression *upr;
|
||||
|
||||
@@ -1087,13 +1115,14 @@ struct TypeSlice : TypeNext
|
||||
const char *kind();
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid = false);
|
||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||
void toJson(JsonOut *json);
|
||||
};
|
||||
|
||||
struct TypeNull : Type
|
||||
class TypeNull : public Type
|
||||
{
|
||||
public:
|
||||
TypeNull();
|
||||
const char *kind();
|
||||
|
||||
@@ -1113,8 +1142,9 @@ struct TypeNull : Type
|
||||
|
||||
//enum InOut { None, In, Out, InOut, Lazy };
|
||||
|
||||
struct Parameter : Object
|
||||
class Parameter : public RootObject
|
||||
{
|
||||
public:
|
||||
//enum InOut inout;
|
||||
StorageClass storageClass;
|
||||
Type *type;
|
||||
|
||||
+74
-151
@@ -39,7 +39,6 @@
|
||||
static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart, Parameters *arguments);
|
||||
static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments);
|
||||
static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flags = 0);
|
||||
static void templateResolve(Match *m, TemplateDeclaration *td, Loc loc, Scope *sc, Objects *tiargs, Expression *ethis, Expressions *arguments);
|
||||
|
||||
/******************************** Expression **************************/
|
||||
|
||||
@@ -182,7 +181,7 @@ AggregateDeclaration *isAggregate(Type *t)
|
||||
/*******************************************
|
||||
* Helper function to turn operator into template argument list
|
||||
*/
|
||||
Objects *opToArg(Scope *sc, enum TOK op)
|
||||
Objects *opToArg(Scope *sc, TOK op)
|
||||
{
|
||||
/* Remove the = from op=
|
||||
*/
|
||||
@@ -236,10 +235,11 @@ Expression *UnaExp::op_overload(Scope *sc)
|
||||
Dsymbol *fd = search_function(ad, Id::opIndexUnary);
|
||||
if (fd)
|
||||
{
|
||||
ae = resolveOpDollar(sc, ae);
|
||||
Expression *e0 = resolveOpDollar(sc, ae);
|
||||
Objects *tiargs = opToArg(sc, op);
|
||||
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, tiargs);
|
||||
e = new CallExp(loc, e, ae->arguments);
|
||||
e = combine(e0, e);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -277,16 +277,18 @@ Expression *UnaExp::op_overload(Scope *sc)
|
||||
Dsymbol *fd = search_function(ad, Id::opSliceUnary);
|
||||
if (fd)
|
||||
{
|
||||
se = resolveOpDollar(sc, se);
|
||||
Expression *e0 = resolveOpDollar(sc, se);
|
||||
Expressions *a = new Expressions();
|
||||
assert(!se->lwr || se->upr);
|
||||
if (se->lwr)
|
||||
{ a->push(se->lwr);
|
||||
{
|
||||
a->push(se->lwr);
|
||||
a->push(se->upr);
|
||||
}
|
||||
Objects *tiargs = opToArg(sc, op);
|
||||
Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, tiargs);
|
||||
e = new CallExp(loc, e, a);
|
||||
e = combine(e0, e);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -388,9 +390,10 @@ Expression *ArrayExp::op_overload(Scope *sc)
|
||||
/* Rewrite op e1[arguments] as:
|
||||
* e1.opIndex(arguments)
|
||||
*/
|
||||
ArrayExp *ae = resolveOpDollar(sc, this);
|
||||
Expression *e = new DotIdExp(loc, ae->e1, fd->ident);
|
||||
e = new CallExp(loc, e, ae->arguments);
|
||||
Expression *e0 = resolveOpDollar(sc, this);
|
||||
Expression *e = new DotIdExp(loc, e1, fd->ident);
|
||||
e = new CallExp(loc, e, arguments);
|
||||
e = combine(e0, e);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -546,8 +549,10 @@ Expression *BinExp::op_overload(Scope *sc)
|
||||
|
||||
args1.setDim(1);
|
||||
args1[0] = e1;
|
||||
expandTuples(&args1);
|
||||
args2.setDim(1);
|
||||
args2[0] = e2;
|
||||
expandTuples(&args2);
|
||||
argsset = 1;
|
||||
|
||||
Match m;
|
||||
@@ -555,32 +560,12 @@ Expression *BinExp::op_overload(Scope *sc)
|
||||
m.last = MATCHnomatch;
|
||||
|
||||
if (s)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args2);
|
||||
}
|
||||
else
|
||||
{ TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
|
||||
}
|
||||
}
|
||||
functionResolve(&m, s, loc, sc, tiargs, e1->type, &args2);
|
||||
|
||||
FuncDeclaration *lastf = m.lastf;
|
||||
|
||||
if (s_r)
|
||||
{
|
||||
FuncDeclaration *fd = s_r->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args1);
|
||||
}
|
||||
else
|
||||
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
|
||||
templateResolve(&m, td, loc, sc, tiargs, e2, &args1);
|
||||
}
|
||||
}
|
||||
functionResolve(&m, s_r, loc, sc, tiargs, e2->type, &args1);
|
||||
|
||||
if (m.count > 1)
|
||||
{
|
||||
@@ -637,10 +622,13 @@ L1:
|
||||
*/
|
||||
|
||||
if (!argsset)
|
||||
{ args1.setDim(1);
|
||||
{
|
||||
args1.setDim(1);
|
||||
args1[0] = e1;
|
||||
expandTuples(&args1);
|
||||
args2.setDim(1);
|
||||
args2[0] = e2;
|
||||
expandTuples(&args2);
|
||||
}
|
||||
|
||||
Match m;
|
||||
@@ -648,31 +636,12 @@ L1:
|
||||
m.last = MATCHnomatch;
|
||||
|
||||
if (s_r)
|
||||
{
|
||||
FuncDeclaration *fd = s_r->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args2);
|
||||
}
|
||||
else
|
||||
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
|
||||
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
|
||||
}
|
||||
}
|
||||
functionResolve(&m, s_r, loc, sc, tiargs, e1->type, &args2);
|
||||
|
||||
FuncDeclaration *lastf = m.lastf;
|
||||
|
||||
if (s)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args1);
|
||||
}
|
||||
else
|
||||
{ TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||
templateResolve(&m, td, loc, sc, tiargs, e2, &args1);
|
||||
}
|
||||
}
|
||||
functionResolve(&m, s, loc, sc, tiargs, e2->type, &args1);
|
||||
|
||||
if (m.count > 1)
|
||||
{
|
||||
@@ -805,8 +774,10 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
|
||||
|
||||
args1.setDim(1);
|
||||
args1[0] = e1;
|
||||
expandTuples(&args1);
|
||||
args2.setDim(1);
|
||||
args2[0] = e2;
|
||||
expandTuples(&args2);
|
||||
|
||||
Match m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
@@ -819,33 +790,13 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
|
||||
}
|
||||
|
||||
if (s)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args2);
|
||||
}
|
||||
else
|
||||
{ TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
|
||||
}
|
||||
}
|
||||
functionResolve(&m, s, loc, sc, tiargs, e1->type, &args2);
|
||||
|
||||
FuncDeclaration *lastf = m.lastf;
|
||||
int count = m.count;
|
||||
|
||||
if (s_r)
|
||||
{
|
||||
FuncDeclaration *fd = s_r->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args1);
|
||||
}
|
||||
else
|
||||
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
|
||||
templateResolve(&m, td, loc, sc, tiargs, e2, &args1);
|
||||
}
|
||||
}
|
||||
functionResolve(&m, s_r, loc, sc, tiargs, e2->type, &args1);
|
||||
|
||||
if (m.count > 1)
|
||||
{
|
||||
@@ -953,7 +904,7 @@ Expression *EqualExp::op_overload(Scope *sc)
|
||||
{ ClassDeclaration *cd1 = t1->isClassHandle();
|
||||
ClassDeclaration *cd2 = t2->isClassHandle();
|
||||
|
||||
if (!(cd1->isCPPinterface() || cd2->isCPPinterface()))
|
||||
if (!(cd1->cpp || cd2->cpp))
|
||||
{
|
||||
/* Rewrite as:
|
||||
* .object.opEquals(e1, e2)
|
||||
@@ -1013,13 +964,14 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
||||
Dsymbol *fd = search_function(ad, Id::opIndexOpAssign);
|
||||
if (fd)
|
||||
{
|
||||
ae = resolveOpDollar(sc, ae);
|
||||
Expression *e0 = resolveOpDollar(sc, ae);
|
||||
Expressions *a = (Expressions *)ae->arguments->copy();
|
||||
a->insert(0, e2);
|
||||
|
||||
Objects *tiargs = opToArg(sc, op);
|
||||
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, tiargs);
|
||||
e = new CallExp(loc, e, a);
|
||||
e = combine(e0, e);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -1057,18 +1009,20 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
||||
Dsymbol *fd = search_function(ad, Id::opSliceOpAssign);
|
||||
if (fd)
|
||||
{
|
||||
se = resolveOpDollar(sc, se);
|
||||
Expression *e0 = resolveOpDollar(sc, se);
|
||||
Expressions *a = new Expressions();
|
||||
a->push(e2);
|
||||
assert(!se->lwr || se->upr);
|
||||
if (se->lwr)
|
||||
{ a->push(se->lwr);
|
||||
{
|
||||
a->push(se->lwr);
|
||||
a->push(se->upr);
|
||||
}
|
||||
|
||||
Objects *tiargs = opToArg(sc, op);
|
||||
Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, tiargs);
|
||||
e = new CallExp(loc, e, a);
|
||||
e = combine(e0, e);
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
@@ -1147,23 +1101,14 @@ Expression *BinAssignExp::op_overload(Scope *sc)
|
||||
|
||||
args2.setDim(1);
|
||||
args2[0] = e2;
|
||||
expandTuples(&args2);
|
||||
|
||||
Match m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.last = MATCHnomatch;
|
||||
|
||||
if (s)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
overloadResolveX(&m, fd, NULL, &args2);
|
||||
}
|
||||
else
|
||||
{ TemplateDeclaration *td = s->isTemplateDeclaration();
|
||||
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
|
||||
}
|
||||
}
|
||||
functionResolve(&m, s, loc, sc, tiargs, e1->type, &args2);
|
||||
|
||||
if (m.count > 1)
|
||||
{
|
||||
@@ -1540,47 +1485,51 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
|
||||
|
||||
static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart, Parameters *arguments)
|
||||
{
|
||||
struct Param3
|
||||
struct ParamOpOver
|
||||
{
|
||||
Parameters *arguments;
|
||||
int mod;
|
||||
MATCH match;
|
||||
FuncDeclaration *fd_best;
|
||||
FuncDeclaration *fd_ambig;
|
||||
|
||||
static int fp(void *param, Dsymbol *s)
|
||||
{
|
||||
Parameters *arguments;
|
||||
int mod;
|
||||
MATCH match;
|
||||
FuncDeclaration *fd_best;
|
||||
FuncDeclaration *fd_ambig;
|
||||
|
||||
static int fp(void *param, FuncDeclaration *f)
|
||||
{
|
||||
Param3 *p = (Param3 *)param;
|
||||
TypeFunction *tf = (TypeFunction *)f->type;
|
||||
MATCH m = MATCHexact;
|
||||
|
||||
if (f->isThis())
|
||||
{ if (!MODimplicitConv(p->mod, tf->mod))
|
||||
m = MATCHnomatch;
|
||||
else if (p->mod != tf->mod)
|
||||
m = MATCHconst;
|
||||
}
|
||||
if (!inferApplyArgTypesY(tf, p->arguments, 1))
|
||||
m = MATCHnomatch;
|
||||
|
||||
if (m > p->match)
|
||||
{ p->fd_best = f;
|
||||
p->fd_ambig = NULL;
|
||||
p->match = m;
|
||||
}
|
||||
else if (m == p->match)
|
||||
p->fd_ambig = f;
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
if (!f)
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
ParamOpOver *p = (ParamOpOver *)param;
|
||||
TypeFunction *tf = (TypeFunction *)f->type;
|
||||
MATCH m = MATCHexact;
|
||||
|
||||
Param3 p;
|
||||
if (f->isThis())
|
||||
{
|
||||
if (!MODimplicitConv(p->mod, tf->mod))
|
||||
m = MATCHnomatch;
|
||||
else if (p->mod != tf->mod)
|
||||
m = MATCHconst;
|
||||
}
|
||||
if (!inferApplyArgTypesY(tf, p->arguments, 1))
|
||||
m = MATCHnomatch;
|
||||
|
||||
if (m > p->match)
|
||||
{
|
||||
p->fd_best = f;
|
||||
p->fd_ambig = NULL;
|
||||
p->match = m;
|
||||
}
|
||||
else if (m == p->match)
|
||||
p->fd_ambig = f;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
ParamOpOver p;
|
||||
p.arguments = arguments;
|
||||
p.mod = ethis->type->mod;
|
||||
p.match = MATCHnomatch;
|
||||
p.fd_best = NULL;
|
||||
p.fd_ambig = NULL;
|
||||
overloadApply(fstart, &Param3::fp, &p);
|
||||
overloadApply(fstart, &p, &ParamOpOver::fp);
|
||||
if (p.fd_best)
|
||||
{
|
||||
inferApplyArgTypesY((TypeFunction *)p.fd_best->type, arguments);
|
||||
@@ -1637,10 +1586,10 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flag
|
||||
arg->type = arg->type->addStorageClass(arg->storageClass);
|
||||
}
|
||||
}
|
||||
Lmatch:
|
||||
Lmatch:
|
||||
return 1;
|
||||
|
||||
Lnomatch:
|
||||
Lnomatch:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1676,29 +1625,3 @@ void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************
|
||||
*/
|
||||
|
||||
static void templateResolve(Match *m, TemplateDeclaration *td, Loc loc, Scope *sc,
|
||||
Objects *tiargs, Expression *ethis, Expressions *arguments)
|
||||
{
|
||||
FuncDeclaration *fd;
|
||||
|
||||
assert(td);
|
||||
fd = td->deduceFunctionTemplate(loc, sc, tiargs, ethis->type, arguments, 1);
|
||||
if (!fd)
|
||||
return;
|
||||
m->anyf = fd;
|
||||
if (m->last >= MATCHexact)
|
||||
{
|
||||
m->nextf = fd;
|
||||
m->count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m->last = MATCHexact;
|
||||
m->lastf = fd;
|
||||
m->count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
+127
-110
@@ -25,13 +25,6 @@
|
||||
#include "init.h"
|
||||
#include "enum.h"
|
||||
|
||||
#ifdef IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
#endif
|
||||
|
||||
static real_t zero; // work around DMC bug for now
|
||||
|
||||
|
||||
/*************************************
|
||||
* If variable has a const initializer,
|
||||
* return that initializer.
|
||||
@@ -51,12 +44,10 @@ Expression *expandVar(int result, VarDeclaration *v)
|
||||
{
|
||||
if (!v->type)
|
||||
{
|
||||
//error("ICE");
|
||||
return e;
|
||||
}
|
||||
Type *tb = v->type->toBasetype();
|
||||
if (result & WANTinterpret ||
|
||||
v->storage_class & STCmanifest ||
|
||||
if ( v->storage_class & STCmanifest ||
|
||||
v->type->toBasetype()->isscalar() ||
|
||||
((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct))
|
||||
)
|
||||
@@ -65,25 +56,25 @@ Expression *expandVar(int result, VarDeclaration *v)
|
||||
{
|
||||
if (v->inuse)
|
||||
{ if (v->storage_class & STCmanifest)
|
||||
{
|
||||
v->error("recursive initialization of constant");
|
||||
goto Lerror;
|
||||
}
|
||||
goto L1;
|
||||
}
|
||||
Expression *ei = v->getConstInitializer();
|
||||
if (!ei)
|
||||
{ if (v->storage_class & STCmanifest)
|
||||
{
|
||||
v->error("enum cannot be initialized with %s", v->init->toChars());
|
||||
goto Lerror;
|
||||
}
|
||||
goto L1;
|
||||
}
|
||||
if (ei->op == TOKconstruct || ei->op == TOKblit)
|
||||
{ AssignExp *ae = (AssignExp *)ei;
|
||||
ei = ae->e2;
|
||||
if (result & WANTinterpret)
|
||||
{
|
||||
v->inuse++;
|
||||
ei = ei->optimize(result);
|
||||
v->inuse--;
|
||||
}
|
||||
else if (ei->isConst() != 1 && ei->op != TOKstring)
|
||||
if (ei->isConst() != 1 && ei->op != TOKstring)
|
||||
goto L1;
|
||||
|
||||
if (ei->type == v->type)
|
||||
@@ -97,8 +88,7 @@ Expression *expandVar(int result, VarDeclaration *v)
|
||||
else
|
||||
goto L1;
|
||||
}
|
||||
else if (!(result & WANTinterpret) &&
|
||||
!(v->storage_class & STCmanifest) &&
|
||||
else if (!(v->storage_class & STCmanifest) &&
|
||||
ei->isConst() != 1 && ei->op != TOKstring &&
|
||||
ei->op != TOKaddress)
|
||||
{
|
||||
@@ -135,6 +125,9 @@ Expression *expandVar(int result, VarDeclaration *v)
|
||||
L1:
|
||||
//if (e) printf("\te = %p, %s, e->type = %d, %s\n", e, e->toChars(), e->type->ty, e->type->toChars());
|
||||
return e;
|
||||
|
||||
Lerror:
|
||||
return new ErrorExp();
|
||||
}
|
||||
|
||||
|
||||
@@ -166,16 +159,6 @@ Expression *fromConstInitializer(int result, Expression *e1)
|
||||
else
|
||||
{
|
||||
e = e1;
|
||||
/* If we needed to interpret, generate an error.
|
||||
* Don't give an error if it's a template parameter
|
||||
*/
|
||||
if (v && (result & WANTinterpret) &&
|
||||
!(v->storage_class & STCtemplateparameter))
|
||||
{
|
||||
e1->error("variable %s cannot be read at compile time", v->toChars());
|
||||
e = e->copy();
|
||||
e->type = Type::terror;
|
||||
}
|
||||
}
|
||||
}
|
||||
return e;
|
||||
@@ -202,11 +185,11 @@ Expression *VarExp::optimize(int result, bool keepLvalue)
|
||||
Expression *TupleExp::optimize(int result, bool keepLvalue)
|
||||
{
|
||||
if (e0)
|
||||
e0 = e0->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e0 = e0->optimize(WANTvalue);
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{
|
||||
Expression *e = (*exps)[i];
|
||||
e = e->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e = e->optimize(WANTvalue);
|
||||
(*exps)[i] = e;
|
||||
}
|
||||
return this;
|
||||
@@ -219,7 +202,7 @@ Expression *ArrayLiteralExp::optimize(int result, bool keepLvalue)
|
||||
for (size_t i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (*elements)[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
e = e->optimize(WANTvalue | (result & WANTexpand));
|
||||
(*elements)[i] = e;
|
||||
}
|
||||
}
|
||||
@@ -232,11 +215,11 @@ Expression *AssocArrayLiteralExp::optimize(int result, bool keepLvalue)
|
||||
for (size_t i = 0; i < keys->dim; i++)
|
||||
{ Expression *e = (*keys)[i];
|
||||
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
e = e->optimize(WANTvalue | (result & WANTexpand));
|
||||
(*keys)[i] = e;
|
||||
|
||||
e = (*values)[i];
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
e = e->optimize(WANTvalue | (result & WANTexpand));
|
||||
(*values)[i] = e;
|
||||
}
|
||||
return this;
|
||||
@@ -253,7 +236,7 @@ Expression *StructLiteralExp::optimize(int result, bool keepLvalue)
|
||||
{ Expression *e = (*elements)[i];
|
||||
if (!e)
|
||||
continue;
|
||||
e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
|
||||
e = e->optimize(WANTvalue | (result & WANTexpand));
|
||||
(*elements)[i] = e;
|
||||
}
|
||||
}
|
||||
@@ -328,8 +311,6 @@ Expression *BoolExp::optimize(int result, bool keepLvalue)
|
||||
Expression *SymOffExp::optimize(int result, bool keepLvalue)
|
||||
{
|
||||
assert(var);
|
||||
if ((result & WANTinterpret) && var->isThreadlocal())
|
||||
error("cannot take address of thread-local variable %s at compile time", var->toChars());
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -382,7 +363,7 @@ Expression *AddrExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
|
||||
{
|
||||
dinteger_t index = ae->e2->toInteger();
|
||||
sinteger_t index = ae->e2->toInteger();
|
||||
VarExp *ve = (VarExp *)ae->e1;
|
||||
if (ve->type->ty == Tsarray
|
||||
&& !ve->var->isImportedSymbol())
|
||||
@@ -390,7 +371,10 @@ Expression *AddrExp::optimize(int result, bool keepLvalue)
|
||||
TypeSArray *ts = (TypeSArray *)ve->type;
|
||||
sinteger_t dim = ts->dim->toInteger();
|
||||
if (index < 0 || index >= dim)
|
||||
{
|
||||
error("array index %lld is out of bounds [0..%lld]", index, dim);
|
||||
return new ErrorExp();
|
||||
}
|
||||
e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
|
||||
e->type = type;
|
||||
return e;
|
||||
@@ -499,16 +483,6 @@ Expression *NewExp::optimize(int result, bool keepLvalue)
|
||||
(*arguments)[i] = e;
|
||||
}
|
||||
}
|
||||
if (result & WANTinterpret)
|
||||
{
|
||||
Expression *eresult = interpret(NULL);
|
||||
if (eresult == EXP_CANT_INTERPRET)
|
||||
return this;
|
||||
if (eresult && eresult != EXP_VOID_INTERPRET)
|
||||
return eresult;
|
||||
else
|
||||
error("cannot evaluate %s at compile time", toChars());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -540,49 +514,19 @@ Expression *CallExp::optimize(int result, bool keepLvalue)
|
||||
return this;
|
||||
|
||||
#if 1
|
||||
if (result & WANTinterpret)
|
||||
{
|
||||
Expression *eresult = interpret(NULL);
|
||||
if (eresult == EXP_CANT_INTERPRET)
|
||||
return e;
|
||||
if (eresult && eresult != EXP_VOID_INTERPRET)
|
||||
e = eresult;
|
||||
else
|
||||
error("cannot evaluate %s at compile time", toChars());
|
||||
}
|
||||
#else
|
||||
if (e1->op == TOKvar)
|
||||
{
|
||||
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
enum BUILTIN b = fd->isBuiltin();
|
||||
BUILTIN b = fd->isBuiltin();
|
||||
if (b)
|
||||
{
|
||||
e = eval_builtin(b, arguments);
|
||||
if (!e) // failed
|
||||
e = this; // evaluate at runtime
|
||||
}
|
||||
else if (result & WANTinterpret)
|
||||
{
|
||||
Expression *eresult = fd->interpret(NULL, arguments);
|
||||
if (eresult && eresult != EXP_VOID_INTERPRET)
|
||||
e = eresult;
|
||||
else
|
||||
error("cannot evaluate %s at compile time", toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e1->op == TOKdotvar && result & WANTinterpret)
|
||||
{ DotVarExp *dve = (DotVarExp *)e1;
|
||||
FuncDeclaration *fd = dve->var->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
Expression *eresult = fd->interpret(NULL, arguments, dve->e1);
|
||||
if (eresult && eresult != EXP_VOID_INTERPRET)
|
||||
e = eresult;
|
||||
else
|
||||
error("cannot evaluate %s at compile time", toChars());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -598,7 +542,7 @@ Expression *CastExp::optimize(int result, bool keepLvalue)
|
||||
//printf("e1->type %s\n", e1->type->toChars());
|
||||
//printf("type = %p\n", type);
|
||||
assert(type);
|
||||
enum TOK op1 = e1->op;
|
||||
TOK op1 = e1->op;
|
||||
#define X 0
|
||||
|
||||
Expression *e1old = e1;
|
||||
@@ -709,7 +653,7 @@ Expression *BinExp::optimize(int result, bool keepLvalue)
|
||||
d_uns64 sz = e1->type->size() * 8;
|
||||
if (i2 < 0 || i2 >= sz)
|
||||
{ error("shift assign by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
|
||||
e2 = new IntegerExp(0);
|
||||
return new ErrorExp();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -722,6 +666,10 @@ Expression *AddExp::optimize(int result, bool keepLvalue)
|
||||
//printf("AddExp::optimize(%s)\n", toChars());
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() && e2->isConst())
|
||||
{
|
||||
if (e1->op == TOKsymoff && e2->op == TOKsymoff)
|
||||
@@ -738,6 +686,10 @@ Expression *MinExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() && e2->isConst())
|
||||
{
|
||||
if (e2->op == TOKsymoff)
|
||||
@@ -755,6 +707,10 @@ Expression *MulExp::optimize(int result, bool keepLvalue)
|
||||
//printf("MulExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
{
|
||||
e = Mul(type, e1, e2);
|
||||
@@ -770,6 +726,10 @@ Expression *DivExp::optimize(int result, bool keepLvalue)
|
||||
//printf("DivExp::optimize(%s)\n", toChars());
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
{
|
||||
e = Div(type, e1, e2);
|
||||
@@ -784,6 +744,10 @@ Expression *ModExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
{
|
||||
e = Mod(type, e1, e2);
|
||||
@@ -798,13 +762,17 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E
|
||||
|
||||
e->e1 = e->e1->optimize(result);
|
||||
e->e2 = e->e2->optimize(result);
|
||||
if (e->e1->op == TOKerror)
|
||||
return e->e1;
|
||||
if (e->e2->op == TOKerror)
|
||||
return e->e2;
|
||||
if (e->e2->isConst() == 1)
|
||||
{
|
||||
sinteger_t i2 = e->e2->toInteger();
|
||||
d_uns64 sz = e->e1->type->size() * 8;
|
||||
if (i2 < 0 || i2 >= sz)
|
||||
{ e->error("shift by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
|
||||
e->e2 = new IntegerExp(0);
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (e->e1->isConst() == 1)
|
||||
ex = (*shift)(e->type, e->e1, e->e2);
|
||||
@@ -835,6 +803,10 @@ Expression *AndExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
e = And(type, e1, e2);
|
||||
else
|
||||
@@ -847,6 +819,10 @@ Expression *OrExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
e = Or(type, e1, e2);
|
||||
else
|
||||
@@ -859,6 +835,10 @@ Expression *XorExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
if (e1->isConst() == 1 && e2->isConst() == 1)
|
||||
e = Xor(type, e1, e2);
|
||||
else
|
||||
@@ -871,6 +851,10 @@ Expression *PowExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
e1 = e1->optimize(result);
|
||||
e2 = e2->optimize(result);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
|
||||
// Replace 1 ^^ x or 1.0^^x by (x, 1)
|
||||
if ((e1->op == TOKint64 && e1->toInteger() == 1) ||
|
||||
@@ -928,6 +912,21 @@ Expression *PowExp::optimize(int result, bool keepLvalue)
|
||||
}
|
||||
e = this;
|
||||
}
|
||||
|
||||
if (e1->op == TOKint64 && e1->toInteger() > 0 &&
|
||||
!((e1->toInteger() - 1) & e1->toInteger()) && // is power of two
|
||||
e2->type->isintegral() && e2->type->isunsigned())
|
||||
{
|
||||
dinteger_t i = e1->toInteger();
|
||||
dinteger_t mul = 1;
|
||||
while ((i >>= 1) > 1)
|
||||
mul++;
|
||||
Expression *shift = new MulExp(loc, e2, new IntegerExp(loc, mul, e2->type));
|
||||
shift->type = Type::tshiftcnt;
|
||||
e = new ShlExp(loc, new IntegerExp(loc, 1, e1->type), shift);
|
||||
e->type = type;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -941,15 +940,10 @@ Expression *CommaExp::optimize(int result, bool keepLvalue)
|
||||
// In particular, if the comma returns a temporary variable, it needs
|
||||
// to be an lvalue (this is particularly important for struct constructors)
|
||||
|
||||
if (result & WANTinterpret)
|
||||
{ // Interpreting comma needs special treatment, because it may
|
||||
// contain compiler-generated declarations.
|
||||
e = interpret(NULL);
|
||||
return (e == EXP_CANT_INTERPRET) ? this : e;
|
||||
}
|
||||
|
||||
e1 = e1->optimize(result & WANTinterpret);
|
||||
e1 = e1->optimize(0);
|
||||
e2 = e2->optimize(result, keepLvalue);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->hasSideEffect())
|
||||
{
|
||||
e = e2;
|
||||
@@ -966,9 +960,12 @@ Expression *ArrayLengthExp::optimize(int result, bool keepLvalue)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | WANTexpand | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTvalue | WANTexpand);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
e = this;
|
||||
if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
|
||||
if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral ||
|
||||
e1->type->toBasetype()->ty == Tsarray)
|
||||
{
|
||||
e = ArrayLength(type, e1);
|
||||
}
|
||||
@@ -978,11 +975,15 @@ Expression *ArrayLengthExp::optimize(int result, bool keepLvalue)
|
||||
Expression *EqualExp::optimize(int result, bool keepLvalue)
|
||||
{
|
||||
//printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTvalue);
|
||||
e2 = e2->optimize(WANTvalue);
|
||||
|
||||
Expression *e1 = fromConstInitializer(result, this->e1);
|
||||
Expression *e2 = fromConstInitializer(result, this->e2);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
|
||||
Expression *e = Equal(op, type, e1, e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
@@ -993,13 +994,19 @@ Expression *EqualExp::optimize(int result, bool keepLvalue)
|
||||
Expression *IdentityExp::optimize(int result, bool keepLvalue)
|
||||
{
|
||||
//printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTvalue);
|
||||
e2 = e2->optimize(WANTvalue);
|
||||
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
if (e2->op == TOKerror)
|
||||
return e2;
|
||||
|
||||
Expression *e = this;
|
||||
|
||||
if ((this->e1->isConst() && this->e2->isConst()) ||
|
||||
(this->e1->op == TOKnull && this->e2->op == TOKnull) ||
|
||||
(result & WANTinterpret))
|
||||
(this->e1->op == TOKnull && this->e2->op == TOKnull)
|
||||
)
|
||||
{
|
||||
e = Identity(op, type, this->e1, this->e2);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
@@ -1042,13 +1049,13 @@ Expression *IndexExp::optimize(int result, bool keepLvalue)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & (WANTinterpret| WANTexpand)));
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTexpand));
|
||||
|
||||
Expression *ex = fromConstInitializer(result, e1);
|
||||
|
||||
// We might know $ now
|
||||
setLengthVarIfKnown(lengthVar, ex);
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTvalue);
|
||||
if (keepLvalue)
|
||||
return this;
|
||||
e = Index(type, ex, e2);
|
||||
@@ -1063,7 +1070,7 @@ Expression *SliceExp::optimize(int result, bool keepLvalue)
|
||||
|
||||
//printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
|
||||
e = this;
|
||||
e1 = e1->optimize(WANTvalue | (result & (WANTinterpret|WANTexpand)));
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTexpand));
|
||||
if (!lwr)
|
||||
{ if (e1->op == TOKstring)
|
||||
{ // Convert slice of string literal into dynamic array
|
||||
@@ -1076,8 +1083,8 @@ Expression *SliceExp::optimize(int result, bool keepLvalue)
|
||||
e1 = fromConstInitializer(result, e1);
|
||||
// We might know $ now
|
||||
setLengthVarIfKnown(lengthVar, e1);
|
||||
lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
|
||||
upr = upr->optimize(WANTvalue | (result & WANTinterpret));
|
||||
lwr = lwr->optimize(WANTvalue);
|
||||
upr = upr->optimize(WANTvalue);
|
||||
e = Slice(type, e1, lwr, upr);
|
||||
if (e == EXP_CANT_INTERPRET)
|
||||
e = this;
|
||||
@@ -1089,7 +1096,9 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("AndAndExp::optimize(%d) %s\n", result, toChars());
|
||||
e1 = e1->optimize(WANTflags | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTflags);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
e = this;
|
||||
if (e1->isBool(FALSE))
|
||||
{
|
||||
@@ -1103,9 +1112,12 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue)
|
||||
}
|
||||
else
|
||||
{
|
||||
e2 = e2->optimize(WANTflags | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTflags);
|
||||
if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
|
||||
{
|
||||
error("void has no value");
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (e1->isConst())
|
||||
{
|
||||
if (e2->isConst())
|
||||
@@ -1128,7 +1140,9 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue)
|
||||
Expression *OrOrExp::optimize(int result, bool keepLvalue)
|
||||
{ Expression *e;
|
||||
|
||||
e1 = e1->optimize(WANTflags | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTflags);
|
||||
if (e1->op == TOKerror)
|
||||
return e1;
|
||||
e = this;
|
||||
if (e1->isBool(TRUE))
|
||||
{ // Replace with (e1, 1)
|
||||
@@ -1138,9 +1152,12 @@ Expression *OrOrExp::optimize(int result, bool keepLvalue)
|
||||
}
|
||||
else
|
||||
{
|
||||
e2 = e2->optimize(WANTflags | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTflags);
|
||||
if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
|
||||
{
|
||||
error("void has no value");
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (e1->isConst())
|
||||
{
|
||||
if (e2->isConst())
|
||||
@@ -1165,8 +1182,8 @@ Expression *CmpExp::optimize(int result, bool keepLvalue)
|
||||
{ Expression *e;
|
||||
|
||||
//printf("CmpExp::optimize() %s\n", toChars());
|
||||
e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
|
||||
e1 = e1->optimize(WANTvalue);
|
||||
e2 = e2->optimize(WANTvalue);
|
||||
|
||||
Expression *e1 = fromConstInitializer(result, this->e1);
|
||||
Expression *e2 = fromConstInitializer(result, this->e2);
|
||||
@@ -1193,7 +1210,7 @@ Expression *CatExp::optimize(int result, bool keepLvalue)
|
||||
Expression *CondExp::optimize(int result, bool keepLvalue)
|
||||
{ Expression *e;
|
||||
|
||||
econd = econd->optimize(WANTflags | (result & WANTinterpret));
|
||||
econd = econd->optimize(WANTflags);
|
||||
if (econd->isBool(TRUE))
|
||||
e = e1->optimize(result, keepLvalue);
|
||||
else if (econd->isBool(FALSE))
|
||||
|
||||
+388
-244
File diff suppressed because it is too large
Load Diff
+41
-40
@@ -19,32 +19,32 @@
|
||||
#include "lexer.h"
|
||||
#include "enum.h"
|
||||
|
||||
struct Type;
|
||||
struct TypeQualified;
|
||||
struct Expression;
|
||||
struct Declaration;
|
||||
struct Statement;
|
||||
struct Import;
|
||||
struct Initializer;
|
||||
struct FuncDeclaration;
|
||||
struct CtorDeclaration;
|
||||
struct PostBlitDeclaration;
|
||||
struct DtorDeclaration;
|
||||
struct StaticCtorDeclaration;
|
||||
struct StaticDtorDeclaration;
|
||||
struct SharedStaticCtorDeclaration;
|
||||
struct SharedStaticDtorDeclaration;
|
||||
struct ConditionalDeclaration;
|
||||
struct InvariantDeclaration;
|
||||
struct UnitTestDeclaration;
|
||||
struct NewDeclaration;
|
||||
struct DeleteDeclaration;
|
||||
struct Condition;
|
||||
struct Module;
|
||||
class Type;
|
||||
class TypeQualified;
|
||||
class Expression;
|
||||
class Declaration;
|
||||
class Statement;
|
||||
class Import;
|
||||
class Initializer;
|
||||
class FuncDeclaration;
|
||||
class CtorDeclaration;
|
||||
class PostBlitDeclaration;
|
||||
class DtorDeclaration;
|
||||
class StaticCtorDeclaration;
|
||||
class StaticDtorDeclaration;
|
||||
class SharedStaticCtorDeclaration;
|
||||
class SharedStaticDtorDeclaration;
|
||||
class ConditionalDeclaration;
|
||||
class InvariantDeclaration;
|
||||
class UnitTestDeclaration;
|
||||
class NewDeclaration;
|
||||
class DeleteDeclaration;
|
||||
class Condition;
|
||||
class Module;
|
||||
struct ModuleDeclaration;
|
||||
struct TemplateDeclaration;
|
||||
struct TemplateInstance;
|
||||
struct StaticAssert;
|
||||
class TemplateDeclaration;
|
||||
class TemplateInstance;
|
||||
class StaticAssert;
|
||||
|
||||
/************************************
|
||||
* These control how parseStatement() works.
|
||||
@@ -60,19 +60,20 @@ enum ParseStatementFlags
|
||||
};
|
||||
|
||||
|
||||
struct Parser : Lexer
|
||||
class Parser : public Lexer
|
||||
{
|
||||
public:
|
||||
ModuleDeclaration *md;
|
||||
enum LINK linkage;
|
||||
LINK linkage;
|
||||
Loc endloc; // set to location of last right curly
|
||||
int inBrackets; // inside [] of array index or slice
|
||||
Loc lookingForElse; // location of lonely if looking for an else
|
||||
|
||||
Parser(Module *module, unsigned char *base, size_t length, int doDocComment);
|
||||
Parser(Module *module, utf8_t *base, size_t length, int doDocComment);
|
||||
|
||||
Dsymbols *parseModule();
|
||||
Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL);
|
||||
Dsymbols *parseAutoDeclarations(StorageClass storageClass, unsigned char *comment);
|
||||
Dsymbols *parseAutoDeclarations(StorageClass storageClass, utf8_t *comment);
|
||||
Dsymbols *parseBlock(Dsymbol **pLastDecl);
|
||||
void composeStorageClass(StorageClass stc);
|
||||
StorageClass parseAttribute(Expressions **pexps);
|
||||
@@ -88,7 +89,7 @@ struct Parser : Lexer
|
||||
StaticAssert *parseStaticAssert();
|
||||
TypeQualified *parseTypeof();
|
||||
Type *parseVector();
|
||||
enum LINK parseLinkage();
|
||||
LINK parseLinkage();
|
||||
Condition *parseDebugCondition();
|
||||
Condition *parseVersionCondition();
|
||||
Condition *parseStaticIfCondition();
|
||||
@@ -111,20 +112,20 @@ struct Parser : Lexer
|
||||
Type *parseBasicType();
|
||||
Type *parseBasicType2(Type *t);
|
||||
Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int* pdisable = NULL);
|
||||
Dsymbols *parseDeclarations(StorageClass storage_class, unsigned char *comment);
|
||||
Dsymbols *parseDeclarations(StorageClass storage_class, utf8_t *comment);
|
||||
void parseContracts(FuncDeclaration *f);
|
||||
void checkDanglingElse(Loc elseloc);
|
||||
/** endPtr used for documented unittests */
|
||||
Statement *parseStatement(int flags, unsigned char** endPtr = NULL);
|
||||
Statement *parseStatement(int flags, utf8_t** endPtr = NULL);
|
||||
Initializer *parseInitializer();
|
||||
Expression *parseDefaultInitExp();
|
||||
void check(Loc loc, enum TOK value);
|
||||
void check(enum TOK value);
|
||||
void check(enum TOK value, const char *string);
|
||||
void checkParens(enum TOK value, Expression *e);
|
||||
int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt);
|
||||
void check(Loc loc, TOK value);
|
||||
void check(TOK value);
|
||||
void check(TOK value, const char *string);
|
||||
void checkParens(TOK value, Expression *e);
|
||||
int isDeclaration(Token *t, int needId, TOK endtok, Token **pt);
|
||||
int isBasicType(Token **pt);
|
||||
int isDeclarator(Token **pt, int *haveId, int *haveTpl, enum TOK endtok);
|
||||
int isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok);
|
||||
int isParameters(Token **pt);
|
||||
int isExpression(Token **pt);
|
||||
int skipParens(Token *t, Token **pt);
|
||||
@@ -154,7 +155,7 @@ struct Parser : Lexer
|
||||
|
||||
Expression *parseNewExp(Expression *thisexp);
|
||||
|
||||
void addComment(Dsymbol *s, unsigned char *blockComment);
|
||||
void addComment(Dsymbol *s, utf8_t *blockComment);
|
||||
};
|
||||
|
||||
// Operator precedence - greater values are higher precedence
|
||||
@@ -180,7 +181,7 @@ enum PREC
|
||||
PREC_primary,
|
||||
};
|
||||
|
||||
extern enum PREC precedence[TOKMAX];
|
||||
extern PREC precedence[TOKMAX];
|
||||
|
||||
void initPrecedence();
|
||||
|
||||
|
||||
+39
-45
@@ -14,20 +14,17 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "aav.h"
|
||||
|
||||
static const size_t prime_list[] = {
|
||||
31UL,
|
||||
97UL, 389UL,
|
||||
1543UL, 6151UL,
|
||||
24593UL, 98317UL,
|
||||
393241UL, 1572869UL,
|
||||
6291469UL, 25165843UL,
|
||||
100663319UL, 402653189UL,
|
||||
1610612741UL, 4294967291UL,
|
||||
};
|
||||
|
||||
inline size_t hash(size_t a)
|
||||
{
|
||||
a ^= (a >> 20) ^ (a >> 12);
|
||||
return a ^ (a >> 7) ^ (a >> 4);
|
||||
}
|
||||
|
||||
struct aaA
|
||||
{
|
||||
@@ -42,9 +39,9 @@ struct AA
|
||||
size_t b_length;
|
||||
size_t nodes; // total number of aaA nodes
|
||||
aaA* binit[4]; // initial value of b[]
|
||||
};
|
||||
|
||||
static const AA bbinit = { NULL, };
|
||||
aaA aafirst; // a lot of these AA's have only one entry
|
||||
};
|
||||
|
||||
/****************************************************
|
||||
* Determine number of entries in associative array.
|
||||
@@ -67,16 +64,20 @@ Value* _aaGet(AA** paa, Key key)
|
||||
|
||||
if (!*paa)
|
||||
{ AA *a = new AA();
|
||||
*a = bbinit;
|
||||
a->b = a->binit;
|
||||
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
|
||||
a->nodes = 0;
|
||||
a->binit[0] = NULL;
|
||||
a->binit[1] = NULL;
|
||||
a->binit[2] = NULL;
|
||||
a->binit[3] = NULL;
|
||||
*paa = a;
|
||||
assert((*paa)->b_length == 4);
|
||||
}
|
||||
//printf("paa = %p, *paa = %p\n", paa, *paa);
|
||||
|
||||
assert((*paa)->b_length);
|
||||
size_t i = (size_t)key % (*paa)->b_length;
|
||||
size_t i = hash((size_t)key) & ((*paa)->b_length - 1);
|
||||
aaA** pe = &(*paa)->b[i];
|
||||
aaA *e;
|
||||
while ((e = *pe) != NULL)
|
||||
@@ -88,15 +89,17 @@ Value* _aaGet(AA** paa, Key key)
|
||||
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = new aaA();
|
||||
|
||||
size_t nodes = ++(*paa)->nodes;
|
||||
e = (nodes != 1) ? new aaA() : &(*paa)->aafirst;
|
||||
//e = new aaA();
|
||||
e->next = NULL;
|
||||
e->key = key;
|
||||
e->value = NULL;
|
||||
*pe = e;
|
||||
|
||||
size_t nodes = ++(*paa)->nodes;
|
||||
//printf("length = %d, nodes = %d\n", paa.a.b.length, nodes);
|
||||
if (nodes > (*paa)->b_length * 4)
|
||||
//printf("length = %d, nodes = %d\n", (*paa)->b_length, nodes);
|
||||
if (nodes > (*paa)->b_length * 2)
|
||||
{
|
||||
//printf("rehash\n");
|
||||
_aaRehash(paa);
|
||||
@@ -114,14 +117,11 @@ Value* _aaGet(AA** paa, Key key)
|
||||
Value _aaGetRvalue(AA* aa, Key key)
|
||||
{
|
||||
//printf("_aaGetRvalue(key = %p)\n", key);
|
||||
if (!aa)
|
||||
return NULL;
|
||||
|
||||
size_t len = aa->b_length;
|
||||
|
||||
if (len)
|
||||
if (aa)
|
||||
{
|
||||
size_t i = (size_t)key % len;
|
||||
size_t i;
|
||||
size_t len = aa->b_length;
|
||||
i = hash((size_t)key) & (len-1);
|
||||
aaA* e = aa->b[i];
|
||||
while (e)
|
||||
{
|
||||
@@ -143,39 +143,33 @@ void _aaRehash(AA** paa)
|
||||
//printf("Rehash\n");
|
||||
if (*paa)
|
||||
{
|
||||
AA newb = bbinit;
|
||||
AA *aa = *paa;
|
||||
size_t len = _aaLen(*paa);
|
||||
if (len)
|
||||
{ size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++)
|
||||
{
|
||||
if (len <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
len = prime_list[i];
|
||||
newb.b = new aaA*[len];
|
||||
memset(newb.b, 0, len * sizeof(aaA*));
|
||||
newb.b_length = len;
|
||||
if (aa)
|
||||
{
|
||||
size_t len = aa->b_length;
|
||||
if (len == 4)
|
||||
len = 32;
|
||||
else
|
||||
len *= 4;
|
||||
aaA** newb = new aaA*[len];
|
||||
memset(newb, 0, len * sizeof(aaA*));
|
||||
|
||||
for (size_t k = 0; k < aa->b_length; k++)
|
||||
{ aaA *e = aa->b[k];
|
||||
while (e)
|
||||
{ aaA* enext = e->next;
|
||||
size_t j = (size_t)e->key % len;
|
||||
e->next = newb.b[j];
|
||||
newb.b[j] = e;
|
||||
size_t j = hash((size_t)e->key) & (len-1);
|
||||
e->next = newb[j];
|
||||
newb[j] = e;
|
||||
e = enext;
|
||||
}
|
||||
}
|
||||
if (aa->b != aa->binit)
|
||||
delete[] aa->b;
|
||||
|
||||
newb.nodes = aa->nodes;
|
||||
aa->b = newb;
|
||||
aa->b_length = len;
|
||||
}
|
||||
|
||||
**paa = newb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
|
||||
// Copyright (c) 1999-2013 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>
|
||||
|
||||
#include "port.h"
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
|
||||
/********************************* Array ****************************/
|
||||
|
||||
Array::Array()
|
||||
{
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
dim = 0;
|
||||
allocdim = SMALLARRAYCAP;
|
||||
}
|
||||
|
||||
Array::~Array()
|
||||
{
|
||||
if (data != &smallarray[0])
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
void Array::mark()
|
||||
{
|
||||
mem.mark(data);
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
||||
}
|
||||
|
||||
void Array::reserve(size_t nentries)
|
||||
{
|
||||
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
|
||||
if (allocdim - dim < nentries)
|
||||
{
|
||||
if (allocdim == 0)
|
||||
{ // Not properly initialized, someone memset it to zero
|
||||
if (nentries <= SMALLARRAYCAP)
|
||||
{ allocdim = SMALLARRAYCAP;
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
}
|
||||
else
|
||||
{ allocdim = nentries;
|
||||
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
else if (allocdim == SMALLARRAYCAP)
|
||||
{
|
||||
allocdim = dim + nentries;
|
||||
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
||||
memcpy(data, &smallarray[0], dim * sizeof(*data));
|
||||
}
|
||||
else
|
||||
{ allocdim = dim + nentries;
|
||||
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Array::setDim(size_t newdim)
|
||||
{
|
||||
if (dim < newdim)
|
||||
{
|
||||
reserve(newdim - dim);
|
||||
}
|
||||
dim = newdim;
|
||||
}
|
||||
|
||||
void Array::fixDim()
|
||||
{
|
||||
if (dim != allocdim)
|
||||
{
|
||||
if (allocdim >= SMALLARRAYCAP)
|
||||
{
|
||||
if (dim <= SMALLARRAYCAP)
|
||||
{
|
||||
memcpy(&smallarray[0], data, dim * sizeof(*data));
|
||||
mem.free(data);
|
||||
}
|
||||
else
|
||||
data = (void **)mem.realloc(data, dim * sizeof(*data));
|
||||
}
|
||||
allocdim = dim;
|
||||
}
|
||||
}
|
||||
|
||||
void Array::push(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
data[dim++] = ptr;
|
||||
}
|
||||
|
||||
void *Array::pop()
|
||||
{
|
||||
return data[--dim];
|
||||
}
|
||||
|
||||
void Array::shift(void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + 1, data, dim * sizeof(*data));
|
||||
data[0] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void Array::insert(size_t index, void *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
||||
data[index] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
|
||||
void Array::insert(size_t index, Array *a)
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
size_t d = a->dim;
|
||||
reserve(d);
|
||||
if (dim != index)
|
||||
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
||||
memcpy(data + index, a->data, d * sizeof(*data));
|
||||
dim += d;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Append array a to this array.
|
||||
*/
|
||||
|
||||
void Array::append(Array *a)
|
||||
{
|
||||
insert(dim, a);
|
||||
}
|
||||
|
||||
void Array::remove(size_t i)
|
||||
{
|
||||
if (dim - i - 1)
|
||||
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
||||
dim--;
|
||||
}
|
||||
|
||||
char *Array::toChars()
|
||||
{
|
||||
char **buf = (char **)malloc(dim * sizeof(char *));
|
||||
assert(buf);
|
||||
size_t len = 2;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
buf[u] = ((Object *)data[u])->toChars();
|
||||
len += strlen(buf[u]) + 1;
|
||||
}
|
||||
char *str = (char *)mem.malloc(len);
|
||||
|
||||
str[0] = '[';
|
||||
char *p = str + 1;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
if (u)
|
||||
*p++ = ',';
|
||||
len = strlen(buf[u]);
|
||||
memcpy(p,buf[u],len);
|
||||
p += len;
|
||||
}
|
||||
*p++ = ']';
|
||||
*p = 0;
|
||||
free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
void Array::zero()
|
||||
{
|
||||
memset(data,0,dim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
void *Array::tos()
|
||||
{
|
||||
return dim ? data[dim - 1] : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
#if _WIN32
|
||||
__cdecl
|
||||
#endif
|
||||
Array_sort_compare(const void *x, const void *y)
|
||||
{
|
||||
Object *ox = *(Object **)x;
|
||||
Object *oy = *(Object **)y;
|
||||
|
||||
return ox->compare(oy);
|
||||
}
|
||||
|
||||
void Array::sort()
|
||||
{
|
||||
if (dim)
|
||||
{
|
||||
qsort(data, dim, sizeof(Object *), Array_sort_compare);
|
||||
}
|
||||
}
|
||||
|
||||
Array *Array::copy()
|
||||
{
|
||||
Array *a = new Array();
|
||||
|
||||
a->setDim(dim);
|
||||
memcpy(a->data, data, dim * sizeof(void *));
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -481,9 +481,9 @@ FM1: // We don't use fprem1 because for some inexplicable
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 };
|
||||
longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 };
|
||||
longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 };
|
||||
longdouble ld_qnan = { 0xC000000000000000ULL, 0x7fff, 0 };
|
||||
longdouble ld_snan = { 0xC000000000000001ULL, 0x7fff, 0 };
|
||||
longdouble ld_inf = { 0x8000000000000000ULL, 0x7fff, 0 };
|
||||
|
||||
longdouble ld_zero = { 0, 0, 0 };
|
||||
longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 };
|
||||
|
||||
+14
-47
@@ -13,19 +13,7 @@
|
||||
#ifndef __LONG_DOUBLE_H__
|
||||
#define __LONG_DOUBLE_H__
|
||||
|
||||
#if IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
typedef real_t longdouble;
|
||||
|
||||
template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
||||
inline size_t ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
if(fmt == 'a' || fmt == 'A')
|
||||
return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max
|
||||
return x.format(buffer, 46);
|
||||
}
|
||||
|
||||
#elif !_MSC_VER // has native 10 byte doubles
|
||||
#if !_MSC_VER // has native 10 byte doubles
|
||||
#include <stdio.h>
|
||||
typedef long double longdouble;
|
||||
typedef volatile long double volatile_longdouble;
|
||||
@@ -143,8 +131,18 @@ inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0)
|
||||
d.sign = sign;
|
||||
return d;
|
||||
}
|
||||
template<typename T> inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
|
||||
//template<typename T> inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; }
|
||||
|
||||
// codegen bug in VS2010/VS2012, if the set() function not inlined
|
||||
// (this passed on stack, but expected in ECX; RVO?)
|
||||
#if _MSC_VER >= 1600
|
||||
#define LDOUBLE_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define LDOUBLE_INLINE inline
|
||||
#endif
|
||||
|
||||
template<typename T> LDOUBLE_INLINE longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
|
||||
|
||||
#undef LDOUBLE_INLINE
|
||||
|
||||
longdouble operator+(longdouble ld1, longdouble ld2);
|
||||
longdouble operator-(longdouble ld1, longdouble ld2);
|
||||
@@ -200,6 +198,7 @@ longdouble tanl (longdouble ld);
|
||||
|
||||
longdouble fmodl(longdouble x, longdouble y);
|
||||
longdouble ldexpl(longdouble ldval, int exp); // see strtold
|
||||
longdouble strtold(const char *p,char **endp);
|
||||
|
||||
inline longdouble fabs (longdouble ld) { return fabsl(ld); }
|
||||
inline longdouble sqrt (longdouble ld) { return sqrtl(ld); }
|
||||
@@ -236,38 +235,6 @@ extern longdouble ld_inf;
|
||||
extern longdouble ld_qnan;
|
||||
extern longdouble ld_snan;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// CLASS numeric_limits<longdouble>
|
||||
template<> class _CRTIMP2_PURE std::numeric_limits<longdouble>
|
||||
: public _Num_float_base
|
||||
{ // limits for type long double
|
||||
public:
|
||||
typedef longdouble _Ty;
|
||||
|
||||
static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; }
|
||||
static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; }
|
||||
static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; }
|
||||
static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); }
|
||||
static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); }
|
||||
static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; }
|
||||
static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; }
|
||||
static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; }
|
||||
|
||||
_STCONS(int, digits, LDBL_MANT_DIG);
|
||||
_STCONS(int, digits10, LDBL_DIG);
|
||||
_STCONS(int, max_exponent, (int)LDBL_MAX_EXP);
|
||||
_STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP);
|
||||
_STCONS(int, min_exponent, (int)LDBL_MIN_EXP);
|
||||
_STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
|
||||
};
|
||||
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
|
||||
|
||||
size_t ld_sprint(char* str, int fmt, longdouble x);
|
||||
|
||||
#endif // !_MSC_VER
|
||||
|
||||
+360
-306
@@ -16,11 +16,33 @@
|
||||
#include <wchar.h>
|
||||
|
||||
double Port::nan = NAN;
|
||||
longdouble Port::ldbl_nan = NAN;
|
||||
longdouble Port::snan;
|
||||
|
||||
double Port::infinity = INFINITY;
|
||||
longdouble Port::ldbl_infinity = INFINITY;
|
||||
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return ::isnan(r);
|
||||
@@ -47,68 +69,22 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::isfinite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::fpclassify(r) == FP_INFINITE);
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return ::signbit(r);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -126,6 +102,36 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
return ::stricmp(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
extern "C" const char * __cdecl __locale_decpoint;
|
||||
|
||||
float Port::strtof(const char *buffer, char **endp)
|
||||
{
|
||||
const char *save = __locale_decpoint;
|
||||
__locale_decpoint = ".";
|
||||
float result = ::strtof(buffer, endp);
|
||||
__locale_decpoint = save;
|
||||
return result;
|
||||
}
|
||||
|
||||
double Port::strtod(const char *buffer, char **endp)
|
||||
{
|
||||
const char *save = __locale_decpoint;
|
||||
__locale_decpoint = ".";
|
||||
double result = ::strtod(buffer, endp);
|
||||
__locale_decpoint = save;
|
||||
return result;
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *buffer, char **endp)
|
||||
{
|
||||
const char *save = __locale_decpoint;
|
||||
__locale_decpoint = ".";
|
||||
longdouble result = ::strtold(buffer, endp);
|
||||
__locale_decpoint = save;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
@@ -134,7 +140,7 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
#pragma warning (disable : 4514)
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <float.h> // for _isnan
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@@ -143,13 +149,12 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
#include <stdlib.h>
|
||||
#include <limits> // for std::numeric_limits
|
||||
|
||||
static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
|
||||
//static unsigned long nanarray[2] = {0,0x7FF80000 };
|
||||
double Port::nan = (*(double *)nanarray);
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
//static unsigned long infinityarray[2] = {0,0x7FF00000 };
|
||||
static double zero = 0;
|
||||
double Port::infinity = 1 / zero;
|
||||
double Port::infinity;
|
||||
longdouble Port::ldbl_infinity;
|
||||
|
||||
double Port::dbl_max = DBL_MAX;
|
||||
double Port::dbl_min = DBL_MIN;
|
||||
@@ -164,7 +169,16 @@ static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union {
|
||||
unsigned long ul[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
Port::ldbl_nan = ld_qnan;
|
||||
Port::snan = ld_snan;
|
||||
Port::infinity = std::numeric_limits<double>::infinity();
|
||||
Port::ldbl_infinity = ld_inf;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
@@ -192,145 +206,22 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isSignallingNan((double) r);
|
||||
}
|
||||
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::_finite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
|
||||
}
|
||||
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&(r))[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
if (y == 0)
|
||||
return 1; // even if x is NAN
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
unsigned _int64 number = 0;
|
||||
int c;
|
||||
int error;
|
||||
#ifndef ULLONG_MAX
|
||||
#define ULLONG_MAX ((unsigned _int64)~0I64)
|
||||
#endif
|
||||
|
||||
while (isspace((unsigned char)*p)) /* skip leading white space */
|
||||
p++;
|
||||
if (*p == '+')
|
||||
p++;
|
||||
switch (base)
|
||||
{ case 0:
|
||||
base = 10; /* assume decimal base */
|
||||
if (*p == '0')
|
||||
{ base = 8; /* could be octal */
|
||||
p++;
|
||||
switch (*p)
|
||||
{ case 'x':
|
||||
case 'X':
|
||||
base = 16; /* hex */
|
||||
p++;
|
||||
break;
|
||||
#if BINARY
|
||||
case 'b':
|
||||
case 'B':
|
||||
base = 2; /* binary */
|
||||
p++;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16: /* skip over '0x' and '0X' */
|
||||
if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
|
||||
p += 2;
|
||||
break;
|
||||
#if BINARY
|
||||
case 2: /* skip over '0b' and '0B' */
|
||||
if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
|
||||
p += 2;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
error = 0;
|
||||
for (;;)
|
||||
{ c = *p;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c = (c & ~0x20) - ('A' - 10);
|
||||
else /* unrecognized character */
|
||||
break;
|
||||
if (c >= base) /* not in number base */
|
||||
break;
|
||||
if ((ULLONG_MAX - c) / base < number)
|
||||
error = 1;
|
||||
number = number * base + c;
|
||||
p++;
|
||||
}
|
||||
if (pend)
|
||||
*pend = (char *)p;
|
||||
if (error)
|
||||
{ number = ULLONG_MAX;
|
||||
errno = ERANGE;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64toa(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
_ui64tow(ull, buffer, 10);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{ double d;
|
||||
|
||||
if ((__int64) ull < 0)
|
||||
{
|
||||
// MSVC doesn't implement the conversion
|
||||
d = (double) (__int64)(ull - 0x8000000000000000i64);
|
||||
d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
|
||||
}
|
||||
else
|
||||
d = (double)(__int64)ull;
|
||||
return d;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
// LOCALE_SLIST for Windows
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -348,6 +239,197 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
return ::stricmp(s1, s2);
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return static_cast<float>(::strtod(p, endp));
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
// See backend/strtold.c.
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if __MINGW32__
|
||||
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <float.h>
|
||||
#include <assert.h>
|
||||
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
static double zero = 0;
|
||||
double Port::infinity = 1 / zero;
|
||||
longdouble Port::ldbl_infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
|
||||
struct PortInitializer
|
||||
{
|
||||
PortInitializer();
|
||||
};
|
||||
|
||||
static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union
|
||||
{ unsigned int ui[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
assert(!signbit(Port::nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
|
||||
|
||||
Port::ldbl_nan = ldbl_nan.ld;
|
||||
assert(!signbit(Port::ldbl_nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
{
|
||||
return isnan(r);
|
||||
}
|
||||
|
||||
int Port::isNan(longdouble r)
|
||||
{
|
||||
return isnan(r);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(double r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||
}
|
||||
|
||||
int Port::isSignallingNan(longdouble r)
|
||||
{
|
||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||
*/
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return isinf(r);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
{
|
||||
char *t = s;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int Port::memicmp(const char *s1, const char *s2, int n)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{ char c1 = s1[i];
|
||||
char c2 = s2[i];
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
result = toupper(c1) - toupper(c2);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Port::stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (;;)
|
||||
{ char c1 = *s1;
|
||||
char c2 = *s2;
|
||||
|
||||
result = c1 - c2;
|
||||
if (result)
|
||||
{
|
||||
result = toupper(c1) - toupper(c2);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
if (!c1)
|
||||
break;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return ::strtof(p, endp);
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::__mingw_strtold(p, endp);
|
||||
}
|
||||
|
||||
// See vcbuild/strtold.c.
|
||||
longdouble strtold(const char *p, char **endp);
|
||||
|
||||
@@ -557,14 +639,20 @@ longdouble Port::strtold(const char *p, char **endp)
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <float.h>
|
||||
#include <assert.h>
|
||||
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = copysign(NAN, 1.0);
|
||||
double Port::infinity = 1 / zero;
|
||||
longdouble Port::ldbl_infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
@@ -578,8 +666,29 @@ static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
union
|
||||
{ unsigned int ui[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
assert(!signbit(Port::nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
|
||||
|
||||
Port::ldbl_nan = ldbl_nan.ld;
|
||||
assert(!signbit(Port::ldbl_nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
|
||||
#if __FreeBSD__ && __i386__
|
||||
// LDBL_MAX comes out as infinity. Fix.
|
||||
static unsigned char x[sizeof(longdouble)] =
|
||||
@@ -640,14 +749,6 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return ::finite(r);
|
||||
}
|
||||
|
||||
#if !defined __HAIKU__
|
||||
#endif
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
#if __APPLE__
|
||||
@@ -660,24 +761,6 @@ int Port::isInfinity(double r)
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
union { double d; long long ll; } u;
|
||||
u.d = r;
|
||||
return u.ll < 0;
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
#if __FreeBSD__ || __OpenBSD__
|
||||
@@ -687,40 +770,12 @@ longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
#if __OpenBSD__
|
||||
assert(0);
|
||||
#else
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
#endif
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -778,6 +833,16 @@ int Port::stricmp(const char *s1, const char *s2)
|
||||
return result;
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return ::strtof(p, endp);
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
@@ -794,14 +859,20 @@ longdouble Port::strtold(const char *p, char **endp)
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
#include <float.h>
|
||||
#include <ieeefp.h>
|
||||
|
||||
double Port::nan;
|
||||
longdouble Port::ldbl_nan;
|
||||
longdouble Port::snan;
|
||||
|
||||
static double zero = 0;
|
||||
double Port::nan = NAN;
|
||||
double Port::infinity = 1 / zero;
|
||||
longdouble Port::ldbl_infinity = 1 / zero;
|
||||
|
||||
double Port::dbl_max = 1.7976931348623157e308;
|
||||
double Port::dbl_min = 5e-324;
|
||||
longdouble Port::ldbl_max = LDBL_MAX;
|
||||
@@ -815,14 +886,28 @@ static PortInitializer portinitializer;
|
||||
|
||||
PortInitializer::PortInitializer()
|
||||
{
|
||||
// gcc nan's have the sign bit set by default, so turn it off
|
||||
// Need the volatile to prevent gcc from doing incorrect
|
||||
// constant folding.
|
||||
volatile longdouble foo;
|
||||
foo = NAN;
|
||||
if (signbit(foo)) // signbit sometimes, not always, set
|
||||
foo = -foo; // turn off sign bit
|
||||
Port::nan = foo;
|
||||
union
|
||||
{ unsigned int ui[2];
|
||||
double d;
|
||||
} nan = {{ 0, 0x7FF80000 }};
|
||||
|
||||
Port::nan = nan.d;
|
||||
assert(!signbit(Port::nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} ldbl_nan = {{ 0, 0xC0000000, 0x7FFF, 0}};
|
||||
|
||||
Port::ldbl_nan = ldbl_nan.ld;
|
||||
assert(!signbit(Port::ldbl_nan));
|
||||
|
||||
union
|
||||
{ unsigned int ui[4];
|
||||
longdouble ld;
|
||||
} snan = {{ 0, 0xA0000000, 0x7FFF, 0 }};
|
||||
|
||||
Port::snan = snan.ld;
|
||||
}
|
||||
|
||||
int Port::isNan(double r)
|
||||
@@ -851,68 +936,22 @@ int Port::isSignallingNan(longdouble r)
|
||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
||||
}
|
||||
|
||||
#undef isfinite
|
||||
int Port::isFinite(double r)
|
||||
{
|
||||
return finite(r);
|
||||
}
|
||||
|
||||
int Port::isInfinity(double r)
|
||||
{
|
||||
return isinf(r);
|
||||
}
|
||||
|
||||
#undef signbit
|
||||
int Port::Signbit(double r)
|
||||
{
|
||||
return (long)(((long *)&r)[1] & 0x80000000);
|
||||
}
|
||||
|
||||
double Port::floor(double d)
|
||||
{
|
||||
return ::floor(d);
|
||||
}
|
||||
|
||||
double Port::pow(double x, double y)
|
||||
{
|
||||
return ::pow(x, y);
|
||||
}
|
||||
|
||||
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||
{
|
||||
return ::fmodl(x, y);
|
||||
}
|
||||
|
||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
||||
int Port::fequal(longdouble x, longdouble y)
|
||||
{
|
||||
return ::strtoull(p, pend, base);
|
||||
}
|
||||
|
||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
||||
{
|
||||
sprintf(buffer, "%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
||||
{
|
||||
swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
double Port::ull_to_double(ulonglong ull)
|
||||
{
|
||||
return (double) ull;
|
||||
}
|
||||
|
||||
const char *Port::list_separator()
|
||||
{
|
||||
return ",";
|
||||
}
|
||||
|
||||
const wchar_t *Port::wlist_separator()
|
||||
{
|
||||
return L",";
|
||||
/* In some cases, the REALPAD bytes get garbage in them,
|
||||
* so be sure and ignore them.
|
||||
*/
|
||||
return memcmp(&x, &y, 10) == 0;
|
||||
}
|
||||
|
||||
char *Port::strupr(char *s)
|
||||
@@ -928,6 +967,21 @@ char *Port::strupr(char *s)
|
||||
return t;
|
||||
}
|
||||
|
||||
float Port::strtof(const char *p, char **endp)
|
||||
{
|
||||
return ::strtof(p, endp);
|
||||
}
|
||||
|
||||
double Port::strtod(const char *p, char **endp)
|
||||
{
|
||||
return ::strtod(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
}
|
||||
|
||||
longdouble Port::strtold(const char *p, char **endp)
|
||||
{
|
||||
return ::strtold(p, endp);
|
||||
|
||||
+12
-23
@@ -13,15 +13,13 @@
|
||||
#if defined(IN_LLVM) && (LDC_LLVM_VER >= 303)
|
||||
#include "llvm/Config/config.h"
|
||||
#endif
|
||||
#include <stdlib.h> // for alloca
|
||||
#include <stdint.h>
|
||||
|
||||
#include "longdouble.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#include <float.h> // for _isnan
|
||||
#include <malloc.h> // for alloca
|
||||
#define strtof strtod
|
||||
#define isnan _isnan
|
||||
|
||||
#include <alloca.h>
|
||||
typedef __int64 longlong;
|
||||
typedef unsigned __int64 ulonglong;
|
||||
#else
|
||||
@@ -29,12 +27,17 @@ typedef long long longlong;
|
||||
typedef unsigned long long ulonglong;
|
||||
#endif
|
||||
|
||||
typedef double d_time;
|
||||
typedef unsigned char utf8_t;
|
||||
|
||||
struct Port
|
||||
{
|
||||
static double nan;
|
||||
static longdouble ldbl_nan;
|
||||
static longdouble snan;
|
||||
|
||||
static double infinity;
|
||||
static longdouble ldbl_infinity;
|
||||
|
||||
static double dbl_max;
|
||||
static double dbl_min;
|
||||
static longdouble ldbl_max;
|
||||
@@ -45,32 +48,18 @@ struct Port
|
||||
static int isSignallingNan(double);
|
||||
static int isSignallingNan(longdouble);
|
||||
|
||||
static int isFinite(double);
|
||||
static int isInfinity(double);
|
||||
static int Signbit(double);
|
||||
|
||||
static double floor(double);
|
||||
static double pow(double x, double y);
|
||||
|
||||
static longdouble fmodl(longdouble x, longdouble y);
|
||||
|
||||
static ulonglong strtoull(const char *p, char **pend, int base);
|
||||
|
||||
static char *ull_to_string(char *buffer, ulonglong ull);
|
||||
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
|
||||
|
||||
// Convert ulonglong to double
|
||||
static double ull_to_double(ulonglong ull);
|
||||
|
||||
// Get locale-dependent list separator
|
||||
static const char *list_separator();
|
||||
static const wchar_t *wlist_separator();
|
||||
static int fequal(longdouble x, longdouble y);
|
||||
|
||||
static char *strupr(char *);
|
||||
|
||||
static int memicmp(const char *s1, const char *s2, int n);
|
||||
static int stricmp(const char *s1, const char *s2);
|
||||
|
||||
static float strtof(const char *p, char **endp);
|
||||
static double strtod(const char *p, char **endp);
|
||||
static longdouble strtold(const char *p, char **endp);
|
||||
};
|
||||
|
||||
|
||||
+56
-5
@@ -11,11 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun
|
||||
#include "../root/rmem.h"
|
||||
#else
|
||||
#include "rmem.h"
|
||||
#endif
|
||||
|
||||
/* This implementation of the storage allocator uses the standard C allocation package.
|
||||
*/
|
||||
@@ -142,6 +138,61 @@ void Mem::addroots(char* pStart, char* pEnd)
|
||||
|
||||
/* =================================================== */
|
||||
|
||||
#if 1
|
||||
|
||||
/* Allocate, but never release
|
||||
*/
|
||||
|
||||
// Allocate a little less than 64kB because the C runtime adds some overhead that
|
||||
// causes the actual memory block to be larger than 64kB otherwise. E.g. the dmc
|
||||
// runtime rounds the size up to 128kB, but the remaining space in the chunk is less
|
||||
// than 64kB, so it cannot be used by another chunk.
|
||||
#define CHUNK_SIZE (4096 * 16 - 64)
|
||||
|
||||
static size_t heapleft = 0;
|
||||
static void *heapp;
|
||||
|
||||
void * operator new(size_t m_size)
|
||||
{
|
||||
// 16 byte alignment is better (and sometimes needed) for doubles
|
||||
m_size = (m_size + 15) & ~15;
|
||||
|
||||
// The layout of the code is selected so the most common case is straight through
|
||||
if (m_size <= heapleft)
|
||||
{
|
||||
L1:
|
||||
heapleft -= m_size;
|
||||
void *p = heapp;
|
||||
heapp = (void *)((char *)heapp + m_size);
|
||||
return p;
|
||||
}
|
||||
|
||||
if (m_size > CHUNK_SIZE)
|
||||
{
|
||||
void *p = malloc(m_size);
|
||||
if (p)
|
||||
return p;
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
return p;
|
||||
}
|
||||
|
||||
heapleft = CHUNK_SIZE;
|
||||
heapp = malloc(CHUNK_SIZE);
|
||||
if (!heapp)
|
||||
{
|
||||
printf("Error: out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
goto L1;
|
||||
}
|
||||
|
||||
void operator delete(void *p)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void * operator new(size_t m_size)
|
||||
{
|
||||
void *p = malloc(m_size);
|
||||
@@ -157,4 +208,4 @@ void operator delete(void *p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+48
-44
@@ -98,42 +98,42 @@ void warning(const char *format, ...)
|
||||
|
||||
/****************************** Object ********************************/
|
||||
|
||||
int Object::equals(Object *o)
|
||||
bool RootObject::equals(RootObject *o)
|
||||
{
|
||||
return o == this;
|
||||
}
|
||||
|
||||
hash_t Object::hashCode()
|
||||
hash_t RootObject::hashCode()
|
||||
{
|
||||
return (hash_t) this;
|
||||
}
|
||||
|
||||
int Object::compare(Object *obj)
|
||||
int RootObject::compare(RootObject *obj)
|
||||
{
|
||||
return this - obj;
|
||||
}
|
||||
|
||||
void Object::print()
|
||||
void RootObject::print()
|
||||
{
|
||||
printf("%s %p\n", toChars(), this);
|
||||
}
|
||||
|
||||
char *Object::toChars()
|
||||
char *RootObject::toChars()
|
||||
{
|
||||
return (char *)"Object";
|
||||
}
|
||||
|
||||
int Object::dyncast()
|
||||
int RootObject::dyncast()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Object::toBuffer(OutBuffer *b)
|
||||
void RootObject::toBuffer(OutBuffer *b)
|
||||
{
|
||||
b->writestring("Object");
|
||||
}
|
||||
|
||||
void Object::mark()
|
||||
void RootObject::mark()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -206,12 +206,12 @@ size_t String::len()
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
int String::equals(Object *obj)
|
||||
bool String::equals(RootObject *obj)
|
||||
{
|
||||
return strcmp(str,((String *)obj)->str) == 0;
|
||||
}
|
||||
|
||||
int String::compare(Object *obj)
|
||||
int String::compare(RootObject *obj)
|
||||
{
|
||||
return strcmp(str,((String *)obj)->str);
|
||||
}
|
||||
@@ -279,7 +279,7 @@ Strings *FileName::splitPath(const char *path)
|
||||
do
|
||||
{ char instring = 0;
|
||||
|
||||
while (isspace((unsigned char)*p)) // skip leading whitespace
|
||||
while (isspace((utf8_t)*p)) // skip leading whitespace
|
||||
p++;
|
||||
buf.reserve(strlen(p) + 1); // guess size of path
|
||||
for (; ; p++)
|
||||
@@ -345,7 +345,7 @@ hash_t FileName::hashCode()
|
||||
// We need a different hashCode because it must be case-insensitive
|
||||
size_t len = strlen(str);
|
||||
hash_t hash = 0;
|
||||
unsigned char *s = (unsigned char *)str;
|
||||
utf8_t *s = (utf8_t *)str;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -384,7 +384,7 @@ hash_t FileName::hashCode()
|
||||
#endif
|
||||
}
|
||||
|
||||
int FileName::compare(Object *obj)
|
||||
int FileName::compare(RootObject *obj)
|
||||
{
|
||||
return compare(str, ((FileName *)obj)->str);
|
||||
}
|
||||
@@ -398,7 +398,7 @@ int FileName::compare(const char *name1, const char *name2)
|
||||
#endif
|
||||
}
|
||||
|
||||
int FileName::equals(Object *obj)
|
||||
bool FileName::equals(RootObject *obj)
|
||||
{
|
||||
return compare(obj) == 0;
|
||||
}
|
||||
@@ -696,7 +696,7 @@ const char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
||||
|
||||
for (size_t i = 0; i < path->dim; i++)
|
||||
{
|
||||
const char *p = path->tdata()[i];
|
||||
const char *p = (*path)[i];
|
||||
const char *n = combine(p, name);
|
||||
|
||||
if (exists(n))
|
||||
@@ -756,7 +756,7 @@ const char *FileName::safeSearchPath(Strings *path, const char *name)
|
||||
for (size_t i = 0; i < path->dim; i++)
|
||||
{
|
||||
const char *cname = NULL;
|
||||
const char *cpath = canonicalName(path->tdata()[i]);
|
||||
const char *cpath = canonicalName((*path)[i]);
|
||||
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
|
||||
// name, (char *)path->data[i], cpath);
|
||||
if (cpath == NULL)
|
||||
@@ -829,7 +829,8 @@ void FileName::ensurePathExists(const char *path)
|
||||
{
|
||||
#if _WIN32
|
||||
size_t len = strlen(path);
|
||||
if (len > 2 && p[-1] == ':' && path + 2 == p)
|
||||
if ((len > 2 && p[-1] == ':' && strcmp(path + 2, p) == 0) ||
|
||||
len == strlen(p))
|
||||
{ mem.free((void *)p);
|
||||
return;
|
||||
}
|
||||
@@ -838,19 +839,20 @@ void FileName::ensurePathExists(const char *path)
|
||||
mem.free((void *)p);
|
||||
}
|
||||
#if _WIN32
|
||||
if (path[strlen(path) - 1] != '\\')
|
||||
#endif
|
||||
#if POSIX
|
||||
if (path[strlen(path) - 1] != '\\')
|
||||
char sep = '\\';
|
||||
#elif POSIX
|
||||
char sep = '/';
|
||||
#endif
|
||||
if (path[strlen(path) - 1] != sep)
|
||||
{
|
||||
//printf("mkdir(%s)\n", path);
|
||||
#if _WIN32
|
||||
if (_mkdir(path))
|
||||
int r = _mkdir(path);
|
||||
#endif
|
||||
#if POSIX
|
||||
if (mkdir(path, 0777))
|
||||
int r = mkdir(path, 0777);
|
||||
#endif
|
||||
if (r)
|
||||
{
|
||||
/* Don't error out if another instance of dmd just created
|
||||
* this directory
|
||||
@@ -1017,7 +1019,7 @@ int File::read()
|
||||
goto err2;
|
||||
}
|
||||
size = buf.st_size;
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
buffer = (utf8_t *) ::malloc(size + 2);
|
||||
if (!buffer)
|
||||
{
|
||||
printf("\tmalloc error, errno = %d\n",errno);
|
||||
@@ -1075,7 +1077,7 @@ err1:
|
||||
ref = 0;
|
||||
|
||||
size = GetFileSize(h,NULL);
|
||||
buffer = (unsigned char *) ::malloc(size + 2);
|
||||
buffer = (utf8_t *) ::malloc(size + 2);
|
||||
if (!buffer)
|
||||
goto err2;
|
||||
|
||||
@@ -1151,7 +1153,7 @@ int File::mmread()
|
||||
if (!ref)
|
||||
mem.free(buffer);
|
||||
ref = 2;
|
||||
buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
|
||||
buffer = (utf8_t *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL);
|
||||
if (CloseHandle(hFileMap) != TRUE)
|
||||
goto Lerr;
|
||||
if (buffer == NULL) // mapping view failed
|
||||
@@ -1359,7 +1361,7 @@ int File::exists()
|
||||
void File::remove()
|
||||
{
|
||||
#if POSIX
|
||||
::remove(this->name->toChars());
|
||||
int dummy = ::remove(this->name->toChars());
|
||||
#elif _WIN32
|
||||
DeleteFileA(this->name->toChars());
|
||||
#else
|
||||
@@ -1469,7 +1471,7 @@ OutBuffer::OutBuffer()
|
||||
|
||||
doindent = 0;
|
||||
level = 0;
|
||||
linehead = 1;
|
||||
notlinehead = 0;
|
||||
}
|
||||
|
||||
OutBuffer::~OutBuffer()
|
||||
@@ -1499,7 +1501,8 @@ void OutBuffer::reserve(size_t nbytes)
|
||||
if (size - offset < nbytes)
|
||||
{
|
||||
size = (offset + nbytes) * 2;
|
||||
data = (unsigned char *)mem.realloc(data, size);
|
||||
size = (size + 15) & ~15;
|
||||
data = (utf8_t *)mem.realloc(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1515,7 +1518,7 @@ void OutBuffer::setsize(size_t size)
|
||||
|
||||
void OutBuffer::write(const void *data, size_t nbytes)
|
||||
{
|
||||
if (doindent && linehead)
|
||||
if (doindent && !notlinehead)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
@@ -1526,14 +1529,14 @@ void OutBuffer::write(const void *data, size_t nbytes)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(nbytes);
|
||||
memcpy(this->data + offset, data, nbytes);
|
||||
offset += nbytes;
|
||||
}
|
||||
|
||||
void OutBuffer::writebstring(unsigned char *string)
|
||||
void OutBuffer::writebstring(utf8_t *string)
|
||||
{
|
||||
write(string,*string + 1);
|
||||
}
|
||||
@@ -1560,12 +1563,12 @@ void OutBuffer::writenl()
|
||||
writeByte('\n');
|
||||
#endif
|
||||
if (doindent)
|
||||
linehead = 1;
|
||||
notlinehead = 0;
|
||||
}
|
||||
|
||||
void OutBuffer::writeByte(unsigned b)
|
||||
{
|
||||
if (doindent && linehead
|
||||
if (doindent && !notlinehead
|
||||
&& b != '\n')
|
||||
{
|
||||
if (level)
|
||||
@@ -1577,7 +1580,7 @@ void OutBuffer::writeByte(unsigned b)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(1);
|
||||
this->data[offset] = (unsigned char)b;
|
||||
@@ -1655,12 +1658,13 @@ void OutBuffer::writewchar(unsigned w)
|
||||
|
||||
void OutBuffer::writeword(unsigned w)
|
||||
{
|
||||
if (doindent && linehead
|
||||
#if _WIN32
|
||||
&& w != 0x0A0D)
|
||||
unsigned newline = 0x0A0D;
|
||||
#else
|
||||
&& w != '\n')
|
||||
unsigned newline = '\n';
|
||||
#endif
|
||||
if (doindent && !notlinehead
|
||||
&& w != newline)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
@@ -1671,7 +1675,7 @@ void OutBuffer::writeword(unsigned w)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(2);
|
||||
*(unsigned short *)(this->data + offset) = (unsigned short)w;
|
||||
@@ -1698,12 +1702,12 @@ void OutBuffer::writeUTF16(unsigned w)
|
||||
|
||||
void OutBuffer::write4(unsigned w)
|
||||
{
|
||||
if (doindent && linehead
|
||||
#if _WIN32
|
||||
&& w != 0x000A000D)
|
||||
bool notnewline = w != 0x000A000D;
|
||||
#else
|
||||
)
|
||||
bool notnewline = true;
|
||||
#endif
|
||||
if (doindent && !notlinehead && notnewline)
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
@@ -1714,7 +1718,7 @@ void OutBuffer::write4(unsigned w)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
linehead = 0;
|
||||
notlinehead = 1;
|
||||
}
|
||||
reserve(4);
|
||||
*(unsigned *)(this->data + offset) = w;
|
||||
@@ -1730,7 +1734,7 @@ void OutBuffer::write(OutBuffer *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void OutBuffer::write(Object *obj)
|
||||
void OutBuffer::write(RootObject *obj)
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
|
||||
+214
-58
@@ -12,10 +12,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef DEBUG
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#include "port.h"
|
||||
#include "rmem.h"
|
||||
|
||||
#if __DMC__
|
||||
#pragma once
|
||||
@@ -30,17 +30,18 @@ typedef size_t hash_t;
|
||||
struct OutBuffer;
|
||||
|
||||
// Can't include arraytypes.h here, need to declare these directly.
|
||||
template <typename TYPE> struct ArrayBase;
|
||||
typedef ArrayBase<struct File> Files;
|
||||
typedef ArrayBase<char> Strings;
|
||||
template <typename TYPE> struct Array;
|
||||
typedef Array<class File> Files;
|
||||
typedef Array<char> Strings;
|
||||
|
||||
|
||||
struct Object
|
||||
class RootObject
|
||||
{
|
||||
Object() { }
|
||||
virtual ~Object() { }
|
||||
public:
|
||||
RootObject() { }
|
||||
virtual ~RootObject() { }
|
||||
|
||||
virtual int equals(Object *o);
|
||||
virtual bool equals(RootObject *o);
|
||||
|
||||
/**
|
||||
* Returns a hash code, useful for things like building hash tables of Objects.
|
||||
@@ -51,7 +52,7 @@ struct Object
|
||||
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
||||
* Useful for sorting Objects.
|
||||
*/
|
||||
virtual int compare(Object *obj);
|
||||
virtual int compare(RootObject *obj);
|
||||
|
||||
/**
|
||||
* Pretty-print an Object. Useful for debugging the old-fashioned way.
|
||||
@@ -74,8 +75,9 @@ struct Object
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct String : Object
|
||||
class String : public RootObject
|
||||
{
|
||||
public:
|
||||
const char *str; // the string itself
|
||||
|
||||
String(const char *str);
|
||||
@@ -85,20 +87,21 @@ struct String : Object
|
||||
static hash_t calcHash(const char *str);
|
||||
hash_t hashCode();
|
||||
size_t len();
|
||||
int equals(Object *obj);
|
||||
int compare(Object *obj);
|
||||
bool equals(RootObject *obj);
|
||||
int compare(RootObject *obj);
|
||||
char *toChars();
|
||||
void print();
|
||||
void mark();
|
||||
};
|
||||
|
||||
struct FileName : String
|
||||
class FileName : public String
|
||||
{
|
||||
public:
|
||||
FileName(const char *str);
|
||||
hash_t hashCode();
|
||||
int equals(Object *obj);
|
||||
bool equals(RootObject *obj);
|
||||
static int equals(const char *name1, const char *name2);
|
||||
int compare(Object *obj);
|
||||
int compare(RootObject *obj);
|
||||
static int compare(const char *name1, const char *name2);
|
||||
static int absolute(const char *name);
|
||||
static const char *ext(const char *);
|
||||
@@ -128,8 +131,9 @@ struct FileName : String
|
||||
static void free(const char *str);
|
||||
};
|
||||
|
||||
struct File : Object
|
||||
class File : public RootObject
|
||||
{
|
||||
public:
|
||||
int ref; // != 0 if this is a reference to someone else's buffer
|
||||
unsigned char *buffer; // data for our file
|
||||
size_t len; // amount of data in buffer[]
|
||||
@@ -233,13 +237,15 @@ struct File : Object
|
||||
void remove(); // delete file
|
||||
};
|
||||
|
||||
struct OutBuffer : Object
|
||||
struct OutBuffer
|
||||
{
|
||||
unsigned char *data;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
|
||||
int doindent, level, linehead;
|
||||
int doindent;
|
||||
int level;
|
||||
int notlinehead;
|
||||
|
||||
OutBuffer();
|
||||
~OutBuffer();
|
||||
@@ -263,7 +269,7 @@ struct OutBuffer : Object
|
||||
void writeUTF16(unsigned w);
|
||||
void write4(unsigned w);
|
||||
void write(OutBuffer *buf);
|
||||
void write(Object *obj);
|
||||
void write(RootObject *obj);
|
||||
void fill0(size_t nbytes);
|
||||
void align(size_t size);
|
||||
void vprintf(const char *format, va_list args);
|
||||
@@ -277,45 +283,178 @@ struct OutBuffer : Object
|
||||
char *extractString();
|
||||
};
|
||||
|
||||
template <typename TYPE>
|
||||
struct Array
|
||||
{
|
||||
size_t dim;
|
||||
void **data;
|
||||
TYPE **data;
|
||||
|
||||
private:
|
||||
size_t allocdim;
|
||||
#define SMALLARRAYCAP 1
|
||||
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
|
||||
TYPE *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
|
||||
|
||||
public:
|
||||
Array();
|
||||
~Array();
|
||||
//Array(const Array&);
|
||||
void mark();
|
||||
char *toChars();
|
||||
Array()
|
||||
{
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
dim = 0;
|
||||
allocdim = SMALLARRAYCAP;
|
||||
}
|
||||
|
||||
void reserve(size_t nentries);
|
||||
void setDim(size_t newdim);
|
||||
void fixDim();
|
||||
void push(void *ptr);
|
||||
void *pop();
|
||||
void shift(void *ptr);
|
||||
void insert(size_t index, void *ptr);
|
||||
void insert(size_t index, Array *a);
|
||||
void append(Array *a);
|
||||
void remove(size_t i);
|
||||
void zero();
|
||||
void *tos();
|
||||
void sort();
|
||||
Array *copy();
|
||||
};
|
||||
~Array()
|
||||
{
|
||||
if (data != &smallarray[0])
|
||||
mem.free(data);
|
||||
}
|
||||
|
||||
void mark()
|
||||
{
|
||||
mem.mark(data);
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
||||
}
|
||||
|
||||
char *toChars()
|
||||
{
|
||||
char **buf = (char **)malloc(dim * sizeof(char *));
|
||||
assert(buf);
|
||||
size_t len = 2;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
buf[u] = ((RootObject *)data[u])->toChars();
|
||||
len += strlen(buf[u]) + 1;
|
||||
}
|
||||
char *str = (char *)mem.malloc(len);
|
||||
|
||||
str[0] = '[';
|
||||
char *p = str + 1;
|
||||
for (size_t u = 0; u < dim; u++)
|
||||
{
|
||||
if (u)
|
||||
*p++ = ',';
|
||||
len = strlen(buf[u]);
|
||||
memcpy(p,buf[u],len);
|
||||
p += len;
|
||||
}
|
||||
*p++ = ']';
|
||||
*p = 0;
|
||||
free(buf);
|
||||
return str;
|
||||
}
|
||||
|
||||
void reserve(size_t nentries)
|
||||
{
|
||||
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", (int)dim, (int)allocdim, (int)nentries);
|
||||
if (allocdim - dim < nentries)
|
||||
{
|
||||
if (allocdim == 0)
|
||||
{ // Not properly initialized, someone memset it to zero
|
||||
if (nentries <= SMALLARRAYCAP)
|
||||
{ allocdim = SMALLARRAYCAP;
|
||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||
}
|
||||
else
|
||||
{ allocdim = nentries;
|
||||
data = (TYPE **)mem.malloc(allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
else if (allocdim == SMALLARRAYCAP)
|
||||
{
|
||||
allocdim = dim + nentries;
|
||||
data = (TYPE **)mem.malloc(allocdim * sizeof(*data));
|
||||
memcpy(data, &smallarray[0], dim * sizeof(*data));
|
||||
}
|
||||
else
|
||||
{ allocdim = dim + nentries;
|
||||
data = (TYPE **)mem.realloc(data, allocdim * sizeof(*data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setDim(size_t newdim)
|
||||
{
|
||||
if (dim < newdim)
|
||||
{
|
||||
reserve(newdim - dim);
|
||||
}
|
||||
dim = newdim;
|
||||
}
|
||||
|
||||
void fixDim()
|
||||
{
|
||||
if (dim != allocdim)
|
||||
{
|
||||
if (allocdim >= SMALLARRAYCAP)
|
||||
{
|
||||
if (dim <= SMALLARRAYCAP)
|
||||
{
|
||||
memcpy(&smallarray[0], data, dim * sizeof(*data));
|
||||
mem.free(data);
|
||||
}
|
||||
else
|
||||
data = (TYPE **)mem.realloc(data, dim * sizeof(*data));
|
||||
}
|
||||
allocdim = dim;
|
||||
}
|
||||
}
|
||||
|
||||
TYPE *pop()
|
||||
{
|
||||
return data[--dim];
|
||||
}
|
||||
|
||||
void shift(TYPE *ptr)
|
||||
{
|
||||
reserve(1);
|
||||
memmove(data + 1, data, dim * sizeof(*data));
|
||||
data[0] = ptr;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void remove(size_t i)
|
||||
{
|
||||
if (dim - i - 1)
|
||||
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
||||
dim--;
|
||||
}
|
||||
|
||||
void zero()
|
||||
{
|
||||
memset(data,0,dim * sizeof(data[0]));
|
||||
}
|
||||
|
||||
TYPE *tos()
|
||||
{
|
||||
return dim ? data[dim - 1] : NULL;
|
||||
}
|
||||
|
||||
void sort()
|
||||
{
|
||||
struct ArraySort
|
||||
{
|
||||
static int
|
||||
#if _WIN32
|
||||
__cdecl
|
||||
#endif
|
||||
Array_sort_compare(const void *x, const void *y)
|
||||
{
|
||||
RootObject *ox = *(RootObject **)x;
|
||||
RootObject *oy = *(RootObject **)y;
|
||||
|
||||
return ox->compare(oy);
|
||||
}
|
||||
};
|
||||
|
||||
if (dim)
|
||||
{
|
||||
qsort(data, dim, sizeof(RootObject *), &ArraySort::Array_sort_compare);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TYPE>
|
||||
struct ArrayBase : Array
|
||||
{
|
||||
TYPE **tdata()
|
||||
{
|
||||
return (TYPE **)data;
|
||||
return data;
|
||||
}
|
||||
|
||||
TYPE*& operator[] (size_t index)
|
||||
@@ -323,36 +462,52 @@ struct ArrayBase : Array
|
||||
#ifdef DEBUG
|
||||
assert(index < dim);
|
||||
#endif
|
||||
return ((TYPE **)data)[index];
|
||||
return data[index];
|
||||
}
|
||||
|
||||
void insert(size_t index, TYPE *v)
|
||||
{
|
||||
Array::insert(index, (void *)v);
|
||||
reserve(1);
|
||||
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
||||
data[index] = v;
|
||||
dim++;
|
||||
}
|
||||
|
||||
void insert(size_t index, ArrayBase *a)
|
||||
void insert(size_t index, Array *a)
|
||||
{
|
||||
Array::insert(index, (Array *)a);
|
||||
if (a)
|
||||
{
|
||||
size_t d = a->dim;
|
||||
reserve(d);
|
||||
if (dim != index)
|
||||
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
||||
memcpy(data + index, a->data, d * sizeof(*data));
|
||||
dim += d;
|
||||
}
|
||||
}
|
||||
|
||||
void append(ArrayBase *a)
|
||||
void append(Array *a)
|
||||
{
|
||||
Array::append((Array *)a);
|
||||
insert(dim, a);
|
||||
}
|
||||
|
||||
void push(TYPE *a)
|
||||
{
|
||||
Array::push((void *)a);
|
||||
reserve(1);
|
||||
data[dim++] = a;
|
||||
}
|
||||
|
||||
ArrayBase *copy()
|
||||
Array *copy()
|
||||
{
|
||||
return (ArrayBase *)Array::copy();
|
||||
Array *a = new Array();
|
||||
|
||||
a->setDim(dim);
|
||||
memcpy(a->data, data, dim * sizeof(*data));
|
||||
return a;
|
||||
}
|
||||
|
||||
typedef int (*ArrayBase_apply_ft_t)(TYPE *, void *);
|
||||
int apply(ArrayBase_apply_ft_t fp, void *param)
|
||||
typedef int (*Array_apply_ft_t)(TYPE *, void *);
|
||||
int apply(Array_apply_ft_t fp, void *param)
|
||||
{
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ TYPE *e = (*this)[i];
|
||||
@@ -368,8 +523,9 @@ struct ArrayBase : Array
|
||||
};
|
||||
|
||||
// TODO: Remove (only used by disabled GC)
|
||||
struct Bits : Object
|
||||
class Bits : public RootObject
|
||||
{
|
||||
public:
|
||||
unsigned bitdim;
|
||||
unsigned allocdim;
|
||||
unsigned *data;
|
||||
|
||||
+158
-11
@@ -21,6 +21,7 @@
|
||||
#include "dsymbol.h"
|
||||
#include "scope.h"
|
||||
#include "declaration.h"
|
||||
#include "statement.h"
|
||||
#include "aggregate.h"
|
||||
#include "module.h"
|
||||
#include "id.h"
|
||||
@@ -50,6 +51,7 @@ Scope::Scope()
|
||||
|
||||
//printf("Scope::Scope() %p\n", this);
|
||||
this->module = NULL;
|
||||
this->instantiatingModule = NULL;
|
||||
this->scopesym = NULL;
|
||||
this->sd = NULL;
|
||||
this->enclosing = NULL;
|
||||
@@ -74,12 +76,11 @@ Scope::Scope()
|
||||
this->inunion = 0;
|
||||
this->nofree = 0;
|
||||
this->noctor = 0;
|
||||
this->noaccesscheck = 0;
|
||||
this->needctfe = 0;
|
||||
this->intypeof = 0;
|
||||
this->speculative = 0;
|
||||
this->parameterSpecialization = 0;
|
||||
this->callSuper = 0;
|
||||
this->fieldinit = NULL;
|
||||
this->fieldinit_dim = 0;
|
||||
this->flags = 0;
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
@@ -92,6 +93,7 @@ Scope::Scope(Scope *enclosing)
|
||||
//printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
|
||||
assert(!(enclosing->flags & SCOPEfree));
|
||||
this->module = enclosing->module;
|
||||
this->instantiatingModule = enclosing->instantiatingModule;
|
||||
this->func = enclosing->func;
|
||||
this->parent = enclosing->parent;
|
||||
this->scopesym = NULL;
|
||||
@@ -125,13 +127,12 @@ Scope::Scope(Scope *enclosing)
|
||||
this->inunion = enclosing->inunion;
|
||||
this->nofree = 0;
|
||||
this->noctor = enclosing->noctor;
|
||||
this->noaccesscheck = enclosing->noaccesscheck;
|
||||
this->needctfe = enclosing->needctfe;
|
||||
this->intypeof = enclosing->intypeof;
|
||||
this->speculative = enclosing->speculative;
|
||||
this->parameterSpecialization = enclosing->parameterSpecialization;
|
||||
this->callSuper = enclosing->callSuper;
|
||||
this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug));
|
||||
this->fieldinit = enclosing->saveFieldInit();
|
||||
this->fieldinit_dim = enclosing->fieldinit_dim;
|
||||
this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe));
|
||||
this->lastdc = NULL;
|
||||
this->lastoffset = 0;
|
||||
this->docbuf = enclosing->docbuf;
|
||||
@@ -183,7 +184,17 @@ Scope *Scope::pop()
|
||||
Scope *enc = enclosing;
|
||||
|
||||
if (enclosing)
|
||||
{
|
||||
enclosing->callSuper |= callSuper;
|
||||
if (enclosing->fieldinit && fieldinit)
|
||||
{
|
||||
size_t dim = fieldinit_dim;
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
enclosing->fieldinit[i] |= fieldinit[i];
|
||||
delete[] fieldinit;
|
||||
fieldinit = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nofree)
|
||||
{ enclosing = freelist;
|
||||
@@ -194,6 +205,19 @@ Scope *Scope::pop()
|
||||
return enc;
|
||||
}
|
||||
|
||||
Scope *Scope::startCTFE()
|
||||
{
|
||||
Scope *sc = this->push();
|
||||
sc->flags = this->flags | SCOPEctfe;
|
||||
return sc;
|
||||
}
|
||||
|
||||
Scope *Scope::endCTFE()
|
||||
{
|
||||
assert(flags & SCOPEctfe);
|
||||
return pop();
|
||||
}
|
||||
|
||||
void Scope::mergeCallSuper(Loc loc, unsigned cs)
|
||||
{
|
||||
// This does a primitive flow analysis to support the restrictions
|
||||
@@ -247,6 +271,131 @@ void Scope::mergeCallSuper(Loc loc, unsigned cs)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned *Scope::saveFieldInit()
|
||||
{
|
||||
unsigned *fi = NULL;
|
||||
if (fieldinit) // copy
|
||||
{
|
||||
size_t dim = fieldinit_dim;
|
||||
fi = new unsigned[dim];
|
||||
fi[0] = dim;
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
fi[i] = fieldinit[i];
|
||||
}
|
||||
return fi;
|
||||
}
|
||||
|
||||
bool mergeFieldInit(Loc loc, unsigned &fieldInit, unsigned fi, bool mustInit)
|
||||
{
|
||||
if (fi != fieldInit)
|
||||
{
|
||||
|
||||
// Have any branches returned?
|
||||
bool aRet = (fi & CSXreturn) != 0;
|
||||
bool bRet = (fieldInit & CSXreturn) != 0;
|
||||
|
||||
bool ok;
|
||||
|
||||
if (aRet)
|
||||
{
|
||||
ok = !mustInit || (fi & CSXthis_ctor);
|
||||
fieldInit = fieldInit;
|
||||
}
|
||||
else if (bRet)
|
||||
{
|
||||
ok = !mustInit || (fieldInit & CSXthis_ctor);
|
||||
fieldInit = fi;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = !mustInit || !((fieldInit ^ fi) & CSXthis_ctor);
|
||||
fieldInit |= fi;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
#if 0
|
||||
// This does a primitive flow analysis to support the restrictions
|
||||
// regarding when and how constructors can appear.
|
||||
// It merges the results of two paths.
|
||||
// The two paths are fieldInit and fi; the result is merged into fieldInit.
|
||||
|
||||
if (fi != fieldInit)
|
||||
{ // Have ALL branches called a constructor?
|
||||
int aAll = (fi & CSXthis_ctor) != 0;
|
||||
int bAll = (fieldInit & CSXthis_ctor) != 0;
|
||||
|
||||
// Have ANY branches called a constructor?
|
||||
bool aAny = (fi & CSXany_ctor) != 0;
|
||||
bool bAny = (fieldInit & CSXany_ctor) != 0;
|
||||
|
||||
// Have any branches returned?
|
||||
bool aRet = (fi & CSXreturn) != 0;
|
||||
bool bRet = (fieldInit & CSXreturn) != 0;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
printf("L%d fieldInit = x%x, fi = x%x\n", __LINE__, fieldInit, fi);
|
||||
|
||||
// If one has returned without a constructor call, there must be never
|
||||
// have been ctor calls in the other.
|
||||
if ( (aRet && !aAny && bAny) ||
|
||||
(bRet && !bAny && aAny))
|
||||
{ ok = false;
|
||||
printf("L%d\n", __LINE__);
|
||||
}
|
||||
// If one branch has called a ctor and then exited, anything the
|
||||
// other branch has done is OK (except returning without a
|
||||
// ctor call, but we already checked that).
|
||||
else if (aRet && aAll)
|
||||
{
|
||||
//fieldInit |= fi & (CSXany_ctor | CSXlabel);
|
||||
printf("L%d -> fieldInit = x%x\n", __LINE__, fieldInit);
|
||||
}
|
||||
else if (bRet && bAll)
|
||||
{
|
||||
fieldInit = fi;// | (fieldInit & (CSXany_ctor | CSXlabel));
|
||||
printf("L%d -> fieldInit = x%x\n", __LINE__, fieldInit);
|
||||
}
|
||||
else
|
||||
{ // Both branches must have called ctors, or both not.
|
||||
ok = (aAll == bAll);
|
||||
// If one returned without a ctor, we must remember that
|
||||
// (Don't bother if we've already found an error)
|
||||
if (ok && aRet && !aAny)
|
||||
fieldInit |= CSXreturn;
|
||||
fieldInit |= fi & (CSXany_ctor | CSXlabel);
|
||||
printf("L%d ok = %d, fieldInit = x%x, fi = x%x\n", __LINE__, ok, fieldInit, fi);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void Scope::mergeFieldInit(Loc loc, unsigned *fies)
|
||||
{
|
||||
if (fieldinit && fies)
|
||||
{
|
||||
FuncDeclaration *f = func;
|
||||
if (fes) f = fes->func;
|
||||
AggregateDeclaration *ad = f->isAggregateMember2();
|
||||
assert(ad);
|
||||
|
||||
for (size_t i = 0; i < ad->fields.dim; i++)
|
||||
{
|
||||
VarDeclaration *v = ad->fields[i];
|
||||
bool mustInit = (v->storage_class & STCnodefaultctor ||
|
||||
v->type->needsNested());
|
||||
|
||||
if (!::mergeFieldInit(loc, fieldinit[i], fies[i], mustInit))
|
||||
{
|
||||
::error(loc, "one path skips field %s", ad->fields[i]->toChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
||||
{ Dsymbol *s;
|
||||
Scope *sc;
|
||||
@@ -282,8 +431,7 @@ Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
|
||||
s = sc->scopesym->search(loc, ident, 0);
|
||||
if (s)
|
||||
{
|
||||
if (global.params.Dversion > 1 &&
|
||||
ident == Id::length &&
|
||||
if (ident == Id::length &&
|
||||
sc->scopesym->isArrayScopeSymbol() &&
|
||||
sc->enclosing &&
|
||||
sc->enclosing->search(loc, ident, NULL))
|
||||
@@ -414,9 +562,8 @@ void *scope_search_fp(void *arg, const char *seed)
|
||||
assert(id);
|
||||
|
||||
Scope *sc = (Scope *)arg;
|
||||
Module::clearCache();
|
||||
Dsymbol *s = sc->search(Loc(), id, NULL);
|
||||
return s;
|
||||
return (void*)s;
|
||||
}
|
||||
|
||||
Dsymbol *Scope::search_correct(Identifier *ident)
|
||||
|
||||
+37
-28
@@ -1,5 +1,5 @@
|
||||
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -14,20 +14,20 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
struct Dsymbol;
|
||||
struct ScopeDsymbol;
|
||||
struct Identifier;
|
||||
struct Module;
|
||||
struct Statement;
|
||||
struct SwitchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct LabelStatement;
|
||||
struct ForeachStatement;
|
||||
struct ClassDeclaration;
|
||||
struct AggregateDeclaration;
|
||||
struct FuncDeclaration;
|
||||
class Dsymbol;
|
||||
class ScopeDsymbol;
|
||||
class Identifier;
|
||||
class Module;
|
||||
class Statement;
|
||||
class SwitchStatement;
|
||||
class TryFinallyStatement;
|
||||
class LabelStatement;
|
||||
class ForeachStatement;
|
||||
class ClassDeclaration;
|
||||
class AggregateDeclaration;
|
||||
class FuncDeclaration;
|
||||
struct DocComment;
|
||||
struct TemplateInstance;
|
||||
class TemplateInstance;
|
||||
|
||||
#if IN_LLVM
|
||||
struct EnclosingHandler;
|
||||
@@ -51,22 +51,26 @@ enum PROT;
|
||||
#define CSXreturn 0x20 // seen a return statement
|
||||
#define CSXany_ctor 0x40 // either this() or super() was called
|
||||
|
||||
#define SCOPEctor 1 // constructor type
|
||||
#define SCOPEstaticif 2 // inside static if
|
||||
#define SCOPEfree 4 // is on free list
|
||||
#define SCOPEstaticassert 8 // inside static assert
|
||||
#define SCOPEdebug 0x10 // inside debug conditional
|
||||
#define SCOPEctor 0x0001 // constructor type
|
||||
#define SCOPEstaticif 0x0002 // inside static if
|
||||
#define SCOPEfree 0x0004 // is on free list
|
||||
#define SCOPEstaticassert 0x0008 // inside static assert
|
||||
#define SCOPEdebug 0x0010 // inside debug conditional
|
||||
|
||||
#define SCOPEinvariant 0x20 // inside invariant code
|
||||
#define SCOPErequire 0x40 // inside in contract code
|
||||
#define SCOPEensure 0x60 // inside out contract code
|
||||
#define SCOPEcontract 0x60 // [mask] we're inside contract code
|
||||
#define SCOPEinvariant 0x0020 // inside invariant code
|
||||
#define SCOPErequire 0x0040 // inside in contract code
|
||||
#define SCOPEensure 0x0060 // inside out contract code
|
||||
#define SCOPEcontract 0x0060 // [mask] we're inside contract code
|
||||
|
||||
#define SCOPEctfe 0x0080 // inside a ctfe-only expression
|
||||
#define SCOPEnoaccesscheck 0x0100 // don't do access checks
|
||||
|
||||
struct Scope
|
||||
{
|
||||
Scope *enclosing; // enclosing Scope
|
||||
|
||||
Module *module; // Root module
|
||||
Module *instantiatingModule; // top level module that started a chain of template instantiations
|
||||
ScopeDsymbol *scopesym; // current symbol
|
||||
ScopeDsymbol *sd; // if in static if, and declaring new symbols,
|
||||
// sd gets the addMember()
|
||||
@@ -91,16 +95,15 @@ struct Scope
|
||||
int noctor; // set if constructor calls aren't allowed
|
||||
int intypeof; // in typeof(exp)
|
||||
bool speculative; // in __traits(compiles) or typeof(exp)
|
||||
int parameterSpecialization; // if in template parameter specialization
|
||||
int noaccesscheck; // don't do access checks
|
||||
int needctfe; // inside a ctfe-only expression
|
||||
|
||||
unsigned callSuper; // primitive flow analysis for constructors
|
||||
unsigned *fieldinit;
|
||||
unsigned fieldinit_dim;
|
||||
|
||||
structalign_t structalign; // alignment for struct members
|
||||
enum LINK linkage; // linkage for external functions
|
||||
LINK linkage; // linkage for external functions
|
||||
|
||||
enum PROT protection; // protection for class members
|
||||
PROT protection; // protection for class members
|
||||
int explicitProtection; // set if in an explicit protection attribute
|
||||
|
||||
StorageClass stc; // storage class
|
||||
@@ -125,8 +128,14 @@ struct Scope
|
||||
Scope *push(ScopeDsymbol *ss);
|
||||
Scope *pop();
|
||||
|
||||
Scope *startCTFE();
|
||||
Scope *endCTFE();
|
||||
|
||||
void mergeCallSuper(Loc loc, unsigned cs);
|
||||
|
||||
unsigned *saveFieldInit();
|
||||
void mergeFieldInit(Loc loc, unsigned *cses);
|
||||
|
||||
Dsymbol *search(Loc loc, Identifier *ident, Dsymbol **pscopesym);
|
||||
Dsymbol *search_correct(Identifier *ident);
|
||||
Dsymbol *insert(Dsymbol *s);
|
||||
|
||||
+461
-405
File diff suppressed because it is too large
Load Diff
+165
-77
@@ -23,40 +23,42 @@
|
||||
|
||||
struct OutBuffer;
|
||||
struct Scope;
|
||||
struct Expression;
|
||||
struct LabelDsymbol;
|
||||
struct Identifier;
|
||||
struct IfStatement;
|
||||
struct ExpStatement;
|
||||
struct DefaultStatement;
|
||||
struct VarDeclaration;
|
||||
struct Condition;
|
||||
struct Module;
|
||||
class Expression;
|
||||
class LabelDsymbol;
|
||||
class Identifier;
|
||||
class IfStatement;
|
||||
class ExpStatement;
|
||||
class DefaultStatement;
|
||||
class VarDeclaration;
|
||||
class Condition;
|
||||
class Module;
|
||||
struct Token;
|
||||
struct InlineCostState;
|
||||
struct InlineDoState;
|
||||
struct InlineScanState;
|
||||
struct ReturnStatement;
|
||||
struct CompoundStatement;
|
||||
struct Parameter;
|
||||
struct StaticAssert;
|
||||
struct AsmStatement;
|
||||
class ErrorStatement;
|
||||
class ReturnStatement;
|
||||
class CompoundStatement;
|
||||
class Parameter;
|
||||
class StaticAssert;
|
||||
class AsmStatement;
|
||||
#if IN_LLVM
|
||||
struct AsmBlockStatement;
|
||||
class AsmBlockStatement;
|
||||
#endif
|
||||
struct GotoStatement;
|
||||
struct ScopeStatement;
|
||||
struct TryCatchStatement;
|
||||
struct TryFinallyStatement;
|
||||
struct CaseStatement;
|
||||
struct DefaultStatement;
|
||||
struct LabelStatement;
|
||||
class GotoStatement;
|
||||
class ScopeStatement;
|
||||
class TryCatchStatement;
|
||||
class TryFinallyStatement;
|
||||
class CaseStatement;
|
||||
class DefaultStatement;
|
||||
class LabelStatement;
|
||||
struct HdrGenState;
|
||||
struct InterState;
|
||||
struct CompiledCtfeFunction;
|
||||
#if IN_LLVM
|
||||
struct CaseStatement;
|
||||
struct LabelStatement;
|
||||
struct SynchronizedStatement;
|
||||
class CaseStatement;
|
||||
class LabelStatement;
|
||||
class SynchronizedStatement;
|
||||
#endif
|
||||
|
||||
enum TOK;
|
||||
@@ -77,8 +79,8 @@ struct IRState;
|
||||
struct Blockx;
|
||||
|
||||
#ifdef IN_GCC
|
||||
union tree_node; typedef union tree_node block;
|
||||
union tree_node; typedef union tree_node elem;
|
||||
typedef union tree_node block;
|
||||
typedef union tree_node elem;
|
||||
#elif IN_LLVM
|
||||
class DValue;
|
||||
typedef DValue elem;
|
||||
@@ -100,11 +102,13 @@ enum BE
|
||||
BEhalt = 0x10,
|
||||
BEbreak = 0x20,
|
||||
BEcontinue = 0x40,
|
||||
BEerrthrow = 0x80,
|
||||
BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
|
||||
};
|
||||
|
||||
struct Statement : Object
|
||||
class Statement : public RootObject
|
||||
{
|
||||
public:
|
||||
Loc loc;
|
||||
virtual ~Statement() {}
|
||||
|
||||
@@ -118,7 +122,6 @@ struct Statement : Object
|
||||
void warning(const char *format, ...);
|
||||
void deprecation(const char *format, ...);
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual ScopeStatement *isScopeStatement() { return NULL; }
|
||||
virtual Statement *semantic(Scope *sc);
|
||||
Statement *semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue);
|
||||
Statement *semanticNoScope(Scope *sc);
|
||||
@@ -136,6 +139,7 @@ struct Statement : Object
|
||||
virtual Statements *flatten(Scope *sc);
|
||||
virtual Expression *interpret(InterState *istate);
|
||||
virtual bool apply(sapply_fp_t fp, void *param);
|
||||
virtual void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
virtual Statement *last();
|
||||
|
||||
virtual int inlineCost(InlineCostState *ics);
|
||||
@@ -147,6 +151,8 @@ struct Statement : Object
|
||||
virtual void toIR(IRState *irs);
|
||||
|
||||
// Avoid dynamic_cast
|
||||
virtual ErrorStatement *isErrorStatement() { return NULL; }
|
||||
virtual ScopeStatement *isScopeStatement() { return NULL; }
|
||||
virtual ExpStatement *isExpStatement() { return NULL; }
|
||||
virtual CompoundStatement *isCompoundStatement() { return NULL; }
|
||||
virtual ReturnStatement *isReturnStatement() { return NULL; }
|
||||
@@ -162,8 +168,23 @@ struct Statement : Object
|
||||
#endif
|
||||
};
|
||||
|
||||
struct PeelStatement : Statement
|
||||
/** Any Statement that fails semantic() or has a component that is an ErrorExp or
|
||||
* a TypeError should return an ErrorStatement from semantic().
|
||||
*/
|
||||
class ErrorStatement : public Statement
|
||||
{
|
||||
public:
|
||||
ErrorStatement();
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit(bool mustNotThrow);
|
||||
|
||||
ErrorStatement *isErrorStatement() { return this; }
|
||||
};
|
||||
|
||||
class PeelStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *s;
|
||||
|
||||
PeelStatement(Statement *s);
|
||||
@@ -171,8 +192,9 @@ struct PeelStatement : Statement
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
};
|
||||
|
||||
struct ExpStatement : Statement
|
||||
class ExpStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
|
||||
ExpStatement(Loc loc, Expression *exp);
|
||||
@@ -181,6 +203,7 @@ struct ExpStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
int blockExit(bool mustNotThrow);
|
||||
bool hasCodeImpl();
|
||||
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
@@ -198,8 +221,9 @@ struct ExpStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct DtorExpStatement : ExpStatement
|
||||
class DtorExpStatement : public ExpStatement
|
||||
{
|
||||
public:
|
||||
/* Wraps an expression that is the destruction of 'var'
|
||||
*/
|
||||
|
||||
@@ -210,8 +234,9 @@ struct DtorExpStatement : ExpStatement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct CompileStatement : Statement
|
||||
class CompileStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
|
||||
CompileStatement(Loc loc, Expression *exp);
|
||||
@@ -222,8 +247,9 @@ struct CompileStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
};
|
||||
|
||||
struct CompoundStatement : Statement
|
||||
class CompoundStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statements *statements;
|
||||
|
||||
CompoundStatement(Loc loc, Statements *s);
|
||||
@@ -238,6 +264,7 @@ struct CompoundStatement : Statement
|
||||
ReturnStatement *isReturnStatement();
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
Statement *last();
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -255,8 +282,9 @@ struct CompoundStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct CompoundDeclarationStatement : CompoundStatement
|
||||
class CompoundDeclarationStatement : public CompoundStatement
|
||||
{
|
||||
public:
|
||||
CompoundDeclarationStatement(Loc loc, Statements *s);
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -265,8 +293,9 @@ struct CompoundDeclarationStatement : CompoundStatement
|
||||
/* The purpose of this is so that continue will go to the next
|
||||
* of the statements, and break will go to the end of the statements.
|
||||
*/
|
||||
struct UnrolledLoopStatement : Statement
|
||||
class UnrolledLoopStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statements *statements;
|
||||
|
||||
UnrolledLoopStatement(Loc loc, Statements *statements);
|
||||
@@ -277,6 +306,7 @@ struct UnrolledLoopStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -287,8 +317,9 @@ struct UnrolledLoopStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ScopeStatement : Statement
|
||||
class ScopeStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *statement;
|
||||
|
||||
ScopeStatement(Loc loc, Statement *s);
|
||||
@@ -302,6 +333,7 @@ struct ScopeStatement : Statement
|
||||
bool hasCodeImpl();
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -311,8 +343,9 @@ struct ScopeStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct WhileStatement : Statement
|
||||
class WhileStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *condition;
|
||||
Statement *body;
|
||||
|
||||
@@ -324,6 +357,7 @@ struct WhileStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -331,8 +365,9 @@ struct WhileStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct DoStatement : Statement
|
||||
class DoStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *body;
|
||||
Expression *condition;
|
||||
|
||||
@@ -344,6 +379,7 @@ struct DoStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -351,13 +387,13 @@ struct DoStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ForStatement : Statement
|
||||
class ForStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *init;
|
||||
Expression *condition;
|
||||
Expression *increment;
|
||||
Statement *body;
|
||||
int nest;
|
||||
|
||||
// When wrapped in try/finally clauses, this points to the outermost one,
|
||||
// which may have an associated label. Internal break/continue statements
|
||||
@@ -366,7 +402,6 @@ struct ForStatement : Statement
|
||||
|
||||
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semanticInit(Scope *sc, Statements *ainit, size_t i);
|
||||
Statement *semantic(Scope *sc);
|
||||
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; }
|
||||
@@ -375,6 +410,7 @@ struct ForStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -384,9 +420,10 @@ struct ForStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ForeachStatement : Statement
|
||||
class ForeachStatement : public Statement
|
||||
{
|
||||
enum TOK op; // TOKforeach or TOKforeach_reverse
|
||||
public:
|
||||
TOK op; // TOKforeach or TOKforeach_reverse
|
||||
Parameters *arguments; // array of Parameter*'s
|
||||
Expression *aggr;
|
||||
Statement *body;
|
||||
@@ -399,7 +436,7 @@ struct ForeachStatement : Statement
|
||||
Statements *cases; // put breaks, continues, gotos and returns here
|
||||
CompoundStatements *gotos; // forward referenced goto's go here
|
||||
|
||||
ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, Expression *aggr, Statement *body);
|
||||
ForeachStatement(Loc loc, TOK op, Parameters *arguments, Expression *aggr, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
bool checkForArgTypes();
|
||||
@@ -410,6 +447,7 @@ struct ForeachStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -418,9 +456,10 @@ struct ForeachStatement : Statement
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct ForeachRangeStatement : Statement
|
||||
class ForeachRangeStatement : public Statement
|
||||
{
|
||||
enum TOK op; // TOKforeach or TOKforeach_reverse
|
||||
public:
|
||||
TOK op; // TOKforeach or TOKforeach_reverse
|
||||
Parameter *arg; // loop index variable
|
||||
Expression *lwr;
|
||||
Expression *upr;
|
||||
@@ -428,7 +467,7 @@ struct ForeachRangeStatement : Statement
|
||||
|
||||
VarDeclaration *key;
|
||||
|
||||
ForeachRangeStatement(Loc loc, enum TOK op, Parameter *arg,
|
||||
ForeachRangeStatement(Loc loc, TOK op, Parameter *arg,
|
||||
Expression *lwr, Expression *upr, Statement *body);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
@@ -437,6 +476,7 @@ struct ForeachRangeStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -445,8 +485,9 @@ struct ForeachRangeStatement : Statement
|
||||
};
|
||||
#endif
|
||||
|
||||
struct IfStatement : Statement
|
||||
class IfStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Parameter *arg;
|
||||
Expression *condition;
|
||||
Statement *ifbody;
|
||||
@@ -459,6 +500,7 @@ struct IfStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int blockExit(bool mustNotThrow);
|
||||
IfStatement *isIfStatement() { return this; }
|
||||
@@ -471,8 +513,9 @@ struct IfStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ConditionalStatement : Statement
|
||||
class ConditionalStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Condition *condition;
|
||||
Statement *ifbody;
|
||||
Statement *elsebody;
|
||||
@@ -487,8 +530,9 @@ struct ConditionalStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct PragmaStatement : Statement
|
||||
class PragmaStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
Expressions *args; // array of Expression's
|
||||
Statement *body;
|
||||
@@ -504,8 +548,9 @@ struct PragmaStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct StaticAssertStatement : Statement
|
||||
class StaticAssertStatement : public Statement
|
||||
{
|
||||
public:
|
||||
StaticAssert *sa;
|
||||
|
||||
StaticAssertStatement(StaticAssert *sa);
|
||||
@@ -516,8 +561,9 @@ struct StaticAssertStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct SwitchStatement : Statement
|
||||
class SwitchStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *condition;
|
||||
Statement *body;
|
||||
bool isFinal;
|
||||
@@ -542,6 +588,7 @@ struct SwitchStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -549,8 +596,9 @@ struct SwitchStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct CaseStatement : Statement
|
||||
class CaseStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
Statement *statement;
|
||||
|
||||
@@ -564,11 +612,12 @@ struct CaseStatement : Statement
|
||||
CaseStatement(Loc loc, Expression *exp, Statement *s);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int compare(Object *obj);
|
||||
int compare(RootObject *obj);
|
||||
int blockExit(bool mustNotThrow);
|
||||
bool comeFromImpl();
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
CaseStatement *isCaseStatement() { return this; }
|
||||
|
||||
@@ -584,8 +633,9 @@ struct CaseStatement : Statement
|
||||
|
||||
#if DMDV2
|
||||
|
||||
struct CaseRangeStatement : Statement
|
||||
class CaseRangeStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *first;
|
||||
Expression *last;
|
||||
Statement *statement;
|
||||
@@ -599,8 +649,9 @@ struct CaseRangeStatement : Statement
|
||||
|
||||
#endif
|
||||
|
||||
struct DefaultStatement : Statement
|
||||
class DefaultStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *statement;
|
||||
#ifdef IN_GCC
|
||||
block *cblock; // back end: label for the block
|
||||
@@ -617,6 +668,7 @@ struct DefaultStatement : Statement
|
||||
bool comeFromImpl();
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
DefaultStatement *isDefaultStatement() { return this; }
|
||||
|
||||
@@ -629,22 +681,25 @@ struct DefaultStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct GotoDefaultStatement : Statement
|
||||
class GotoDefaultStatement : public Statement
|
||||
{
|
||||
public:
|
||||
SwitchStatement *sw;
|
||||
|
||||
GotoDefaultStatement(Loc loc);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct GotoCaseStatement : Statement
|
||||
class GotoCaseStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp; // NULL, or which case to goto
|
||||
CaseStatement *cs; // case statement it resolves to
|
||||
SwitchStatement *sw;
|
||||
@@ -653,23 +708,27 @@ struct GotoCaseStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct SwitchErrorStatement : Statement
|
||||
class SwitchErrorStatement : public Statement
|
||||
{
|
||||
public:
|
||||
SwitchErrorStatement(Loc loc);
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ReturnStatement : Statement
|
||||
class ReturnStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
bool implicit0; // this is an implicit "return 0;"
|
||||
|
||||
@@ -679,6 +738,7 @@ struct ReturnStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -690,14 +750,16 @@ struct ReturnStatement : Statement
|
||||
ReturnStatement *isReturnStatement() { return this; }
|
||||
};
|
||||
|
||||
struct BreakStatement : Statement
|
||||
class BreakStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
|
||||
BreakStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -709,14 +771,16 @@ struct BreakStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ContinueStatement : Statement
|
||||
class ContinueStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
|
||||
ContinueStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -728,8 +792,9 @@ struct ContinueStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct SynchronizedStatement : Statement
|
||||
class SynchronizedStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
Statement *body;
|
||||
|
||||
@@ -754,8 +819,9 @@ struct SynchronizedStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct WithStatement : Statement
|
||||
class WithStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
Statement *body;
|
||||
VarDeclaration *wthis;
|
||||
@@ -767,14 +833,16 @@ struct WithStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct TryCatchStatement : Statement
|
||||
class TryCatchStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *body;
|
||||
Catches *catches;
|
||||
|
||||
@@ -786,6 +854,7 @@ struct TryCatchStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
@@ -793,8 +862,9 @@ struct TryCatchStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct Catch : Object
|
||||
class Catch : public RootObject
|
||||
{
|
||||
public:
|
||||
Loc loc;
|
||||
Type *type;
|
||||
Identifier *ident;
|
||||
@@ -810,8 +880,9 @@ struct Catch : Object
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct TryFinallyStatement : Statement
|
||||
class TryFinallyStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *body;
|
||||
Statement *finalbody;
|
||||
|
||||
@@ -825,14 +896,16 @@ struct TryFinallyStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct OnScopeStatement : Statement
|
||||
class OnScopeStatement : public Statement
|
||||
{
|
||||
public:
|
||||
TOK tok;
|
||||
Statement *statement;
|
||||
|
||||
@@ -845,12 +918,14 @@ struct OnScopeStatement : Statement
|
||||
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct ThrowStatement : Statement
|
||||
class ThrowStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
bool internalThrow; // was generated by the compiler,
|
||||
// wasn't present in source code
|
||||
@@ -861,14 +936,16 @@ struct ThrowStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
};
|
||||
|
||||
struct DebugStatement : Statement
|
||||
class DebugStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Statement *statement;
|
||||
|
||||
DebugStatement(Loc loc, Statement *statement);
|
||||
@@ -879,8 +956,9 @@ struct DebugStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct GotoStatement : Statement
|
||||
class GotoStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
LabelDsymbol *label;
|
||||
#if !IN_LLVM
|
||||
@@ -895,13 +973,15 @@ struct GotoStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
struct LabelStatement : Statement
|
||||
class LabelStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
Statement *statement;
|
||||
#if !IN_LLVM
|
||||
@@ -910,6 +990,7 @@ struct LabelStatement : Statement
|
||||
TryFinallyStatement *enclosingFinally;
|
||||
Statement* enclosingScopeExit;
|
||||
#endif
|
||||
Statement *gotoTarget; // interpret
|
||||
block *lblock; // back end
|
||||
|
||||
Blocks *fwdrefs; // forward references to this LabelStatement
|
||||
@@ -922,6 +1003,7 @@ struct LabelStatement : Statement
|
||||
bool comeFromImpl();
|
||||
Expression *interpret(InterState *istate);
|
||||
bool apply(sapply_fp_t fp, void *param);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -934,16 +1016,18 @@ struct LabelStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct LabelDsymbol : Dsymbol
|
||||
class LabelDsymbol : public Dsymbol
|
||||
{
|
||||
public:
|
||||
LabelStatement *statement;
|
||||
|
||||
LabelDsymbol(Identifier *ident);
|
||||
LabelDsymbol *isLabel();
|
||||
};
|
||||
|
||||
struct AsmStatement : Statement
|
||||
class AsmStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Token *tokens;
|
||||
code *asmcode;
|
||||
unsigned asmalign; // alignment of this statement
|
||||
@@ -957,6 +1041,7 @@ struct AsmStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
bool comeFromImpl();
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -974,8 +1059,9 @@ struct AsmStatement : Statement
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ImportStatement : Statement
|
||||
class ImportStatement : public Statement
|
||||
{
|
||||
public:
|
||||
Dsymbols *imports; // Array of Import's
|
||||
|
||||
ImportStatement(Loc loc, Dsymbols *imports);
|
||||
@@ -984,6 +1070,7 @@ struct ImportStatement : Statement
|
||||
int blockExit(bool mustNotThrow);
|
||||
bool hasCodeImpl();
|
||||
Expression *interpret(InterState *istate);
|
||||
void ctfeCompile(CompiledCtfeFunction *ccf);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -995,8 +1082,9 @@ struct ImportStatement : Statement
|
||||
};
|
||||
|
||||
#if IN_LLVM
|
||||
struct AsmBlockStatement : CompoundStatement
|
||||
class AsmBlockStatement : public CompoundStatement
|
||||
{
|
||||
public:
|
||||
TryFinallyStatement* enclosingFinally;
|
||||
Statement* enclosingScopeExit;
|
||||
|
||||
|
||||
+15
-5
@@ -55,9 +55,16 @@ void StaticAssert::semantic2(Scope *sc)
|
||||
ScopeDsymbol *sd = new ScopeDsymbol();
|
||||
sc = sc->push(sd);
|
||||
sc->flags |= SCOPEstaticassert;
|
||||
Expression *e = exp->ctfeSemantic(sc);
|
||||
|
||||
sc = sc->startCTFE();
|
||||
Expression *e = exp->semantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc->endCTFE();
|
||||
sc = sc->pop();
|
||||
|
||||
// Simplify expression, to make error messages nicer if CTFE fails
|
||||
e = e->optimize(0);
|
||||
|
||||
if (!e->type->checkBoolean())
|
||||
{
|
||||
if (e->type->toBasetype() != Type::terror)
|
||||
@@ -73,11 +80,14 @@ void StaticAssert::semantic2(Scope *sc)
|
||||
else if (e->isBool(FALSE))
|
||||
{
|
||||
if (msg)
|
||||
{ HdrGenState hgs;
|
||||
{
|
||||
HdrGenState hgs;
|
||||
OutBuffer buf;
|
||||
|
||||
msg = msg->ctfeSemantic(sc);
|
||||
sc = sc->startCTFE();
|
||||
msg = msg->semantic(sc);
|
||||
msg = resolveProperties(sc, msg);
|
||||
sc = sc->endCTFE();
|
||||
msg = msg->ctfeInterpret();
|
||||
hgs.console = 1;
|
||||
StringExp * s = msg->toString();
|
||||
@@ -101,11 +111,11 @@ void StaticAssert::semantic2(Scope *sc)
|
||||
}
|
||||
}
|
||||
|
||||
int StaticAssert::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
bool StaticAssert::oneMember(Dsymbol **ps, Identifier *ident)
|
||||
{
|
||||
//printf("StaticAssert::oneMember())\n");
|
||||
*ps = NULL;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StaticAssert::inlineScan()
|
||||
|
||||
+4
-3
@@ -17,11 +17,12 @@
|
||||
|
||||
#include "dsymbol.h"
|
||||
|
||||
struct Expression;
|
||||
class Expression;
|
||||
struct HdrGenState;
|
||||
|
||||
struct StaticAssert : Dsymbol
|
||||
class StaticAssert : public Dsymbol
|
||||
{
|
||||
public:
|
||||
Expression *exp;
|
||||
Expression *msg;
|
||||
|
||||
@@ -32,7 +33,7 @@ struct StaticAssert : Dsymbol
|
||||
void semantic(Scope *sc);
|
||||
void semantic2(Scope *sc);
|
||||
void inlineScan();
|
||||
int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
void toObjFile(int multiobj);
|
||||
const char *kind();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
+182
-51
@@ -22,6 +22,75 @@
|
||||
#include "template.h"
|
||||
|
||||
FuncDeclaration *StructDeclaration::xerreq; // object.xopEquals
|
||||
FuncDeclaration *StructDeclaration::xerrcmp; // object.xopCmp
|
||||
|
||||
bool inNonRoot(Dsymbol *s)
|
||||
{
|
||||
if (!s || !s->parent)
|
||||
return false;
|
||||
s = s->parent;
|
||||
for (; s; s = s->parent)
|
||||
{
|
||||
if (TemplateInstance *ti = s->isTemplateInstance())
|
||||
{
|
||||
if (!ti->instantiatingModule || !ti->instantiatingModule->isRoot())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
else if (Module *m = s->isModule())
|
||||
{
|
||||
if (!m->isRoot())
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Search toHash member function for TypeInfo_Struct.
|
||||
* const hash_t toHash();
|
||||
*/
|
||||
FuncDeclaration *search_toHash(StructDeclaration *sd)
|
||||
{
|
||||
Dsymbol *s = search_function(sd, Id::tohash);
|
||||
FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fd)
|
||||
{
|
||||
static TypeFunction *tftohash;
|
||||
if (!tftohash)
|
||||
{
|
||||
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
|
||||
tftohash->mod = MODconst;
|
||||
tftohash = (TypeFunction *)tftohash->merge();
|
||||
}
|
||||
|
||||
fd = fd->overloadExactMatch(tftohash);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Search toString member function for TypeInfo_Struct.
|
||||
* string toString();
|
||||
*/
|
||||
FuncDeclaration *search_toString(StructDeclaration *sd)
|
||||
{
|
||||
Dsymbol *s = search_function(sd, Id::tostring);
|
||||
FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fd)
|
||||
{
|
||||
static TypeFunction *tftostring;
|
||||
if (!tftostring)
|
||||
{
|
||||
tftostring = new TypeFunction(NULL, Type::tstring, 0, LINKd);
|
||||
tftostring = (TypeFunction *)tftostring->merge();
|
||||
}
|
||||
|
||||
fd = fd->overloadExactMatch(tftostring);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/********************************* AggregateDeclaration ****************************/
|
||||
|
||||
@@ -66,7 +135,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
#endif
|
||||
}
|
||||
|
||||
enum PROT AggregateDeclaration::prot()
|
||||
PROT AggregateDeclaration::prot()
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
@@ -109,6 +178,10 @@ void AggregateDeclaration::semantic3(Scope *sc)
|
||||
//printf("AggregateDeclaration::semantic3(%s)\n", toChars());
|
||||
if (members)
|
||||
{
|
||||
StructDeclaration *sd = isStructDeclaration();
|
||||
if (!sc) // from runDeferredSemantic3 for TypeInfo generation
|
||||
goto Lxop;
|
||||
|
||||
sc = sc->push(this);
|
||||
sc->parent = this;
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
@@ -116,20 +189,13 @@ void AggregateDeclaration::semantic3(Scope *sc)
|
||||
Dsymbol *s = (*members)[i];
|
||||
s->semantic3(sc);
|
||||
}
|
||||
|
||||
if (StructDeclaration *sd = isStructDeclaration())
|
||||
{
|
||||
//if (sd->xeq != NULL) printf("sd = %s xeq @ [%s]\n", sd->toChars(), sd->loc.toChars());
|
||||
//assert(sd->xeq == NULL);
|
||||
if (sd->xeq == NULL)
|
||||
sd->xeq = sd->buildXopEquals(sc);
|
||||
}
|
||||
sc = sc->pop();
|
||||
|
||||
if (!getRTInfo && Type::rtinfo &&
|
||||
(!isDeprecated() || global.params.useDeprecated) && // don't do it for unused deprecated types
|
||||
(type && type->ty != Terror)) // or error types
|
||||
{ // Evaluate: gcinfo!type
|
||||
{
|
||||
// Evaluate: RTinfo!type
|
||||
Objects *tiargs = new Objects();
|
||||
tiargs->push(type);
|
||||
TemplateInstance *ti = new TemplateInstance(loc, Type::rtinfo, tiargs);
|
||||
@@ -138,10 +204,55 @@ void AggregateDeclaration::semantic3(Scope *sc)
|
||||
ti->semantic3(sc);
|
||||
Dsymbol *s = ti->toAlias();
|
||||
Expression *e = new DsymbolExp(Loc(), s, 0);
|
||||
e = e->ctfeSemantic(ti->tempdecl->scope);
|
||||
|
||||
Scope *sc2 = ti->tempdecl->scope->startCTFE();
|
||||
sc2->instantiatingModule = sc->instantiatingModule ? sc->instantiatingModule : sc->module;
|
||||
e = e->semantic(sc2);
|
||||
sc2->endCTFE();
|
||||
|
||||
e = e->ctfeInterpret();
|
||||
getRTInfo = e;
|
||||
}
|
||||
|
||||
if (sd)
|
||||
{
|
||||
Lxop:
|
||||
if (sd->xeq &&
|
||||
sd->xeq->scope &&
|
||||
sd->xeq->semanticRun < PASSsemantic3done)
|
||||
{
|
||||
unsigned errors = global.startGagging();
|
||||
sd->xeq->semantic3(sd->xeq->scope);
|
||||
if (global.endGagging(errors))
|
||||
sd->xeq = sd->xerreq;
|
||||
}
|
||||
|
||||
if (sd->xcmp &&
|
||||
sd->xcmp->scope &&
|
||||
sd->xcmp->semanticRun < PASSsemantic3done)
|
||||
{
|
||||
unsigned errors = global.startGagging();
|
||||
sd->xcmp->semantic3(sd->xcmp->scope);
|
||||
if (global.endGagging(errors))
|
||||
sd->xcmp = sd->xerrcmp;
|
||||
}
|
||||
|
||||
FuncDeclaration *ftostr = search_toString(sd);
|
||||
if (ftostr &&
|
||||
ftostr->scope &&
|
||||
ftostr->semanticRun < PASSsemantic3done)
|
||||
{
|
||||
ftostr->semantic3(ftostr->scope);
|
||||
}
|
||||
|
||||
FuncDeclaration *ftohash = search_toHash(sd);
|
||||
if (ftohash &&
|
||||
ftohash->scope &&
|
||||
ftohash->semanticRun < PASSsemantic3done)
|
||||
{
|
||||
ftohash->semantic3(ftohash->scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,8 +275,6 @@ unsigned AggregateDeclaration::size(Loc loc)
|
||||
//printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope);
|
||||
if (loc.linnum == 0)
|
||||
loc = this->loc;
|
||||
if (!members)
|
||||
error(loc, "unknown size");
|
||||
if (sizeok != SIZEOKdone && scope)
|
||||
semantic(NULL);
|
||||
|
||||
@@ -209,8 +318,13 @@ unsigned AggregateDeclaration::size(Loc loc)
|
||||
L1: ;
|
||||
}
|
||||
|
||||
if (sizeok != SIZEOKdone)
|
||||
{ error(loc, "no size yet for forward reference");
|
||||
if (!members)
|
||||
{
|
||||
error(loc, "unknown size");
|
||||
}
|
||||
else if (sizeok != SIZEOKdone)
|
||||
{
|
||||
error(loc, "no size yet for forward reference");
|
||||
//*(char*)0=0;
|
||||
}
|
||||
return structsize;
|
||||
@@ -226,7 +340,7 @@ bool AggregateDeclaration::isDeprecated()
|
||||
return isdeprecated;
|
||||
}
|
||||
|
||||
int AggregateDeclaration::isExport()
|
||||
bool AggregateDeclaration::isExport()
|
||||
{
|
||||
return protection == PROTexport;
|
||||
}
|
||||
@@ -244,11 +358,11 @@ void AggregateDeclaration::alignmember(
|
||||
//printf("alignment = %d, size = %d, offset = %d\n",alignment,size,offset);
|
||||
switch (alignment)
|
||||
{
|
||||
case 1:
|
||||
case (structalign_t) 1:
|
||||
// No alignment
|
||||
break;
|
||||
|
||||
case STRUCTALIGN_DEFAULT:
|
||||
case (structalign_t) STRUCTALIGN_DEFAULT:
|
||||
{ /* Must match what the corresponding C compiler's default
|
||||
* alignment behavior is.
|
||||
*/
|
||||
@@ -427,6 +541,25 @@ int AggregateDeclaration::numFieldsInUnion(int firstIndex)
|
||||
return count;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Look for constructor declaration.
|
||||
*/
|
||||
void AggregateDeclaration::searchCtor()
|
||||
{
|
||||
ctor = search(Loc(), Id::ctor, 0);
|
||||
if (ctor)
|
||||
{
|
||||
if (!(ctor->isCtorDeclaration() ||
|
||||
ctor->isTemplateDeclaration() ||
|
||||
ctor->isOverloadSet()))
|
||||
{
|
||||
error("%s %s is not a constructor; identifiers starting with __ are reserved for the implementation", ctor->kind(), ctor->toChars());
|
||||
errors = true;
|
||||
ctor = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************* StructDeclaration ****************************/
|
||||
|
||||
StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
||||
@@ -440,6 +573,7 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
|
||||
postblit = NULL;
|
||||
|
||||
xeq = NULL;
|
||||
xcmp = NULL;
|
||||
alignment = 0;
|
||||
#endif
|
||||
arg1type = NULL;
|
||||
@@ -500,14 +634,13 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
Scope *scx = NULL;
|
||||
if (scope)
|
||||
{ sc = scope;
|
||||
{
|
||||
sc = scope;
|
||||
scx = scope; // save so we don't make redundant copies
|
||||
scope = NULL;
|
||||
}
|
||||
|
||||
int errors = global.errors;
|
||||
|
||||
unsigned dprogress_save = Module::dprogress;
|
||||
int errors = global.errors;
|
||||
|
||||
parent = sc->parent;
|
||||
type = type->semantic(loc, sc);
|
||||
@@ -547,15 +680,10 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
* resolve individual members like enums.
|
||||
*/
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
{ Dsymbol *s = (*members)[i];
|
||||
/* There are problems doing this in the general case because
|
||||
* Scope keeps track of things like 'offset'
|
||||
*/
|
||||
//if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
|
||||
{
|
||||
//printf("struct: setScope %s %s\n", s->kind(), s->toChars());
|
||||
s->setScope(sc2);
|
||||
}
|
||||
{
|
||||
Dsymbol *s = (*members)[i];
|
||||
//printf("struct: setScope %s %s\n", s->kind(), s->toChars());
|
||||
s->setScope(sc2);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < members->dim; i++)
|
||||
@@ -572,14 +700,10 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
if (sizeok == SIZEOKnone && s->isAliasDeclaration())
|
||||
finalizeSize(sc2);
|
||||
}
|
||||
|
||||
// Ungag errors when not speculative
|
||||
unsigned oldgag = global.gag;
|
||||
if (global.isSpeculativeGagging() && !isSpeculative())
|
||||
{
|
||||
global.gag = 0;
|
||||
}
|
||||
Ungag ungag = ungagSpeculative();
|
||||
s->semantic(sc2);
|
||||
global.gag = oldgag;
|
||||
}
|
||||
finalizeSize(sc2);
|
||||
|
||||
@@ -704,6 +828,19 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
buildOpAssign(sc2);
|
||||
buildOpEquals(sc2);
|
||||
|
||||
xeq = buildXopEquals(sc2);
|
||||
xcmp = buildXopCmp(sc2);
|
||||
|
||||
/* Even if the struct is merely imported and its semantic3 is not run,
|
||||
* the TypeInfo object would be speculatively stored in each object
|
||||
* files. To set correct function pointer, run semantic3 for xeq and xcmp.
|
||||
*/
|
||||
//if ((xeq && xeq != xerreq || xcmp && xcmp != xerrcmp) && isImportedSym(this))
|
||||
// Module::addDeferredSemantic3(this);
|
||||
/* Defer requesting semantic3 until TypeInfo generation is actually invoked.
|
||||
* See Type::getTypeInfo().
|
||||
*/
|
||||
#endif
|
||||
inv = buildInv(sc2);
|
||||
|
||||
@@ -711,9 +848,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
/* Look for special member functions.
|
||||
*/
|
||||
#if DMDV2
|
||||
ctor = search(Loc(), Id::ctor, 0);
|
||||
#endif
|
||||
searchCtor();
|
||||
aggNew = (NewDeclaration *)search(Loc(), Id::classNew, 0);
|
||||
aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete, 0);
|
||||
|
||||
@@ -735,6 +870,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
if (global.errors != errors)
|
||||
{ // The type is no good.
|
||||
type = Type::terror;
|
||||
this->errors = true;
|
||||
}
|
||||
|
||||
if (deferred && !global.gag)
|
||||
@@ -743,14 +879,12 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
deferred->semantic3(sc);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
|
||||
{
|
||||
printf("this = %p %s\n", this, this->toChars());
|
||||
printf("type = %d sym = %p\n", type->ty, ((TypeStruct *)type)->sym);
|
||||
error("failed semantic analysis");
|
||||
this->errors = true;
|
||||
type = Type::terror;
|
||||
}
|
||||
#endif
|
||||
assert(type->ty != Tstruct || ((TypeStruct *)type)->sym == this);
|
||||
}
|
||||
|
||||
Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
|
||||
@@ -830,13 +964,10 @@ bool StructDeclaration::isPOD()
|
||||
assert(v && v->isField());
|
||||
if (v->storage_class & STCref)
|
||||
continue;
|
||||
Type *tv = v->type->toBasetype();
|
||||
while (tv->ty == Tsarray)
|
||||
{ TypeSArray *ta = (TypeSArray *)tv;
|
||||
tv = tv->nextOf()->toBasetype();
|
||||
}
|
||||
Type *tv = v->type->baseElemOf();
|
||||
if (tv->ty == Tstruct)
|
||||
{ TypeStruct *ts = (TypeStruct *)tv;
|
||||
{
|
||||
TypeStruct *ts = (TypeStruct *)tv;
|
||||
StructDeclaration *sd = ts->sym;
|
||||
if (!sd->isPOD())
|
||||
return false;
|
||||
|
||||
+2
-1
@@ -14,7 +14,7 @@
|
||||
// At present it is incomplete, but in future it should grow to contain
|
||||
// most or all target machine and target O/S specific information.
|
||||
|
||||
struct Type;
|
||||
class Type;
|
||||
|
||||
struct Target
|
||||
{
|
||||
@@ -26,6 +26,7 @@ struct Target
|
||||
static void init();
|
||||
static unsigned alignsize(Type* type);
|
||||
static unsigned fieldalign(Type* type);
|
||||
static unsigned critsecsize();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+1958
-1212
File diff suppressed because it is too large
Load Diff
+114
-90
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2012 by Digital Mars
|
||||
// Copyright (c) 1999-2013 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -24,52 +24,56 @@
|
||||
|
||||
|
||||
struct OutBuffer;
|
||||
struct Identifier;
|
||||
struct TemplateInstance;
|
||||
struct TemplateParameter;
|
||||
struct TemplateTypeParameter;
|
||||
struct TemplateThisParameter;
|
||||
struct TemplateValueParameter;
|
||||
struct TemplateAliasParameter;
|
||||
struct TemplateTupleParameter;
|
||||
struct Type;
|
||||
struct TypeQualified;
|
||||
struct TypeTypeof;
|
||||
class Identifier;
|
||||
class TemplateInstance;
|
||||
class TemplateParameter;
|
||||
class TemplateTypeParameter;
|
||||
class TemplateThisParameter;
|
||||
class TemplateValueParameter;
|
||||
class TemplateAliasParameter;
|
||||
class TemplateTupleParameter;
|
||||
class Type;
|
||||
class TypeQualified;
|
||||
class TypeTypeof;
|
||||
struct Scope;
|
||||
struct Expression;
|
||||
struct AliasDeclaration;
|
||||
struct FuncDeclaration;
|
||||
class Expression;
|
||||
class AliasDeclaration;
|
||||
class FuncDeclaration;
|
||||
struct HdrGenState;
|
||||
struct Parameter;
|
||||
class Parameter;
|
||||
enum MATCH;
|
||||
enum PASS;
|
||||
|
||||
struct Tuple : Object
|
||||
class Tuple : public RootObject
|
||||
{
|
||||
public:
|
||||
Objects objects;
|
||||
|
||||
int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType()
|
||||
};
|
||||
|
||||
|
||||
struct TemplateDeclaration : ScopeDsymbol
|
||||
class TemplateDeclaration : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
TemplateParameters *parameters; // array of TemplateParameter's
|
||||
|
||||
TemplateParameters *origParameters; // originals for Ddoc
|
||||
Expression *constraint;
|
||||
TemplateInstances instances; // array of TemplateInstance's
|
||||
|
||||
// Hash table to look up TemplateInstance's of this TemplateDeclaration
|
||||
Array<TemplateInstances> buckets;
|
||||
size_t numinstances; // number of instances in the hash table
|
||||
|
||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||
TemplateDeclaration *overroot; // first in overnext list
|
||||
|
||||
enum PASS semanticRun; // 1 semantic() run
|
||||
FuncDeclaration *funcroot; // first function in unified overload list
|
||||
|
||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||
|
||||
int literal; // this template declaration is a literal
|
||||
int ismixin; // template declaration is only to be used as a mixin
|
||||
enum PROT protection;
|
||||
PROT protection;
|
||||
|
||||
struct Previous
|
||||
{ Previous *prev;
|
||||
@@ -82,7 +86,7 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
Expression *constraint, Dsymbols *decldefs, int ismixin);
|
||||
Dsymbol *syntaxCopy(Dsymbol *);
|
||||
void semantic(Scope *sc);
|
||||
int overloadInsert(Dsymbol *s);
|
||||
bool overloadInsert(Dsymbol *s);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
bool hasStaticCtorOrDtor();
|
||||
const char *kind();
|
||||
@@ -91,21 +95,23 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
void emitComment(Scope *sc);
|
||||
void toJson(JsonOut *json);
|
||||
virtual void jsonProperties(JsonOut *json);
|
||||
enum PROT prot();
|
||||
PROT prot();
|
||||
// void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag);
|
||||
MATCH leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs);
|
||||
MATCH matchWithInstance(Scope *sc, TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag);
|
||||
MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs);
|
||||
|
||||
MATCH deduceFunctionTemplateMatch(Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, Objects *dedargs);
|
||||
FuncDeclaration *deduceFunctionTemplate(Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, int flags = 0);
|
||||
Object *declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
|
||||
MATCH deduceFunctionTemplateMatch(FuncDeclaration *f, Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, Objects *dedargs);
|
||||
RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o);
|
||||
FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Type *tthis, Expressions *fargs);
|
||||
TemplateInstance *findExistingInstance(TemplateInstance *tithis, Expressions *fargs);
|
||||
TemplateInstance *addInstance(TemplateInstance *ti);
|
||||
void removeInstance(TemplateInstance *handle);
|
||||
|
||||
TemplateDeclaration *isTemplateDeclaration() { return this; }
|
||||
|
||||
TemplateTupleParameter *isVariadic();
|
||||
int isOverloadable();
|
||||
bool isOverloadable();
|
||||
|
||||
void makeParamNamesVisibleInConstraint(Scope *paramscope, Expressions *fargs);
|
||||
#if IN_LLVM
|
||||
@@ -114,8 +120,9 @@ struct TemplateDeclaration : ScopeDsymbol
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TemplateParameter
|
||||
class TemplateParameter
|
||||
{
|
||||
public:
|
||||
/* For type-parameter:
|
||||
* template Foo(ident) // specType is set to NULL
|
||||
* template Foo(ident : specType)
|
||||
@@ -145,11 +152,11 @@ struct TemplateParameter
|
||||
|
||||
virtual TemplateParameter *syntaxCopy() = 0;
|
||||
virtual void declareParameter(Scope *sc) = 0;
|
||||
virtual void semantic(Scope *) = 0;
|
||||
virtual void print(Object *oarg, Object *oded) = 0;
|
||||
virtual void semantic(Scope *sc, TemplateParameters *parameters) = 0;
|
||||
virtual void print(RootObject *oarg, RootObject *oded) = 0;
|
||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||
virtual Object *specialization() = 0;
|
||||
virtual Object *defaultArg(Loc loc, Scope *sc) = 0;
|
||||
virtual RootObject *specialization() = 0;
|
||||
virtual RootObject *defaultArg(Loc loc, Scope *sc) = 0;
|
||||
|
||||
/* If TemplateParameter's match as far as overloading goes.
|
||||
*/
|
||||
@@ -157,15 +164,17 @@ struct TemplateParameter
|
||||
|
||||
/* Match actual argument against parameter.
|
||||
*/
|
||||
virtual MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) = 0;
|
||||
virtual MATCH matchArg(Loc loc, Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
virtual MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) = 0;
|
||||
|
||||
/* Create dummy argument based on parameter.
|
||||
*/
|
||||
virtual void *dummyArg() = 0;
|
||||
};
|
||||
|
||||
struct TemplateTypeParameter : TemplateParameter
|
||||
class TemplateTypeParameter : public TemplateParameter
|
||||
{
|
||||
public:
|
||||
/* Syntax:
|
||||
* ident : specType = defaultType
|
||||
*/
|
||||
@@ -179,19 +188,20 @@ struct TemplateTypeParameter : TemplateParameter
|
||||
TemplateTypeParameter *isTemplateTypeParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void semantic(Scope *sc, TemplateParameters *parameters);
|
||||
void print(RootObject *oarg, RootObject *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
RootObject *specialization();
|
||||
RootObject *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
struct TemplateThisParameter : TemplateTypeParameter
|
||||
class TemplateThisParameter : public TemplateTypeParameter
|
||||
{
|
||||
public:
|
||||
/* Syntax:
|
||||
* this ident : specType = defaultType
|
||||
*/
|
||||
@@ -204,8 +214,9 @@ struct TemplateThisParameter : TemplateTypeParameter
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TemplateValueParameter : TemplateParameter
|
||||
class TemplateValueParameter : public TemplateParameter
|
||||
{
|
||||
public:
|
||||
/* Syntax:
|
||||
* valType ident : specValue = defaultValue
|
||||
*/
|
||||
@@ -221,45 +232,47 @@ struct TemplateValueParameter : TemplateParameter
|
||||
TemplateValueParameter *isTemplateValueParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void semantic(Scope *sc, TemplateParameters *parameters);
|
||||
void print(RootObject *oarg, RootObject *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
RootObject *specialization();
|
||||
RootObject *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateAliasParameter : TemplateParameter
|
||||
class TemplateAliasParameter : public TemplateParameter
|
||||
{
|
||||
public:
|
||||
/* Syntax:
|
||||
* specType ident : specAlias = defaultAlias
|
||||
*/
|
||||
|
||||
Type *specType;
|
||||
Object *specAlias;
|
||||
Object *defaultAlias;
|
||||
RootObject *specAlias;
|
||||
RootObject *defaultAlias;
|
||||
|
||||
static Dsymbol *sdummy;
|
||||
|
||||
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias);
|
||||
TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, RootObject *specAlias, RootObject *defaultAlias);
|
||||
|
||||
TemplateAliasParameter *isTemplateAliasParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void semantic(Scope *sc, TemplateParameters *parameters);
|
||||
void print(RootObject *oarg, RootObject *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
RootObject *specialization();
|
||||
RootObject *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateTupleParameter : TemplateParameter
|
||||
class TemplateTupleParameter : public TemplateParameter
|
||||
{
|
||||
public:
|
||||
/* Syntax:
|
||||
* ident ...
|
||||
*/
|
||||
@@ -269,25 +282,26 @@ struct TemplateTupleParameter : TemplateParameter
|
||||
TemplateTupleParameter *isTemplateTupleParameter();
|
||||
TemplateParameter *syntaxCopy();
|
||||
void declareParameter(Scope *sc);
|
||||
void semantic(Scope *);
|
||||
void print(Object *oarg, Object *oded);
|
||||
void semantic(Scope *sc, TemplateParameters *parameters);
|
||||
void print(RootObject *oarg, RootObject *oded);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Object *specialization();
|
||||
Object *defaultArg(Loc loc, Scope *sc);
|
||||
RootObject *specialization();
|
||||
RootObject *defaultArg(Loc loc, Scope *sc);
|
||||
int overloadMatch(TemplateParameter *);
|
||||
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
MATCH matchArg(Loc loc, Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
|
||||
void *dummyArg();
|
||||
};
|
||||
|
||||
struct TemplateInstance : ScopeDsymbol
|
||||
class TemplateInstance : public ScopeDsymbol
|
||||
{
|
||||
public:
|
||||
/* Given:
|
||||
* foo!(args) =>
|
||||
* name = foo
|
||||
* tiargs = args
|
||||
*/
|
||||
Identifier *name;
|
||||
//Identifiers idents;
|
||||
Objects *tiargs; // Array of Types/Expressions of template
|
||||
// instance arguments [int*, char, 10*10]
|
||||
|
||||
@@ -295,19 +309,21 @@ struct TemplateInstance : ScopeDsymbol
|
||||
// to TemplateDeclaration.parameters
|
||||
// [int, char, 100]
|
||||
|
||||
TemplateDeclaration *tempdecl; // referenced by foo.bar.abc
|
||||
Dsymbol *tempdecl; // referenced by foo.bar.abc
|
||||
TemplateInstance *inst; // refer to existing instance
|
||||
TemplateInstance *tinst; // enclosing template instance
|
||||
ScopeDsymbol *argsym; // argument symbol table
|
||||
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
|
||||
// sole member
|
||||
WithScopeSymbol *withsym; // if a member of a with statement
|
||||
enum PASS semanticRun; // has semantic() been done?
|
||||
int semantictiargsdone; // has semanticTiargs() been done?
|
||||
int nest; // for recursion detection
|
||||
int havetempdecl; // 1 if used second constructor
|
||||
Dsymbol *enclosing; // if referencing local symbols, this is the context
|
||||
int speculative; // 1 if only instantiated with errors gagged
|
||||
int nest; // for recursion detection
|
||||
bool semantictiargsdone; // has semanticTiargs() been done?
|
||||
bool havetempdecl; // if used second constructor
|
||||
bool speculative; // if only instantiated with errors gagged
|
||||
Dsymbol *enclosing; // if referencing local symbols, this is the context
|
||||
hash_t hash; // cached result of hashCode()
|
||||
Expressions *fargs; // for function template, these are the function arguments
|
||||
Module *instantiatingModule; // the top module that instantiated this instance
|
||||
#ifdef IN_GCC
|
||||
/* On some targets, it is necessary to know whether a symbol
|
||||
will be emitted in the output or not before the symbol
|
||||
@@ -325,25 +341,30 @@ struct TemplateInstance : ScopeDsymbol
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void toCBufferTiargs(OutBuffer *buf, HdrGenState *hgs);
|
||||
Dsymbol *toAlias(); // resolve real symbol
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
int needsTypeInference(Scope *sc);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
char *toChars();
|
||||
const char *mangle(bool isv = false);
|
||||
void printInstantiationTrace();
|
||||
Identifier *getIdent();
|
||||
int compare(RootObject *o);
|
||||
hash_t hashCode();
|
||||
|
||||
#if IN_DMD
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
#endif
|
||||
|
||||
// Internal
|
||||
bool findTemplateDeclaration(Scope *sc);
|
||||
bool updateTemplateDeclaration(Scope *sc, Dsymbol *s);
|
||||
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
|
||||
bool semanticTiargs(Scope *sc);
|
||||
bool findTemplateDeclaration(Scope *sc);
|
||||
bool findBestMatch(Scope *sc, Expressions *fargs);
|
||||
bool needsTypeInference(Scope *sc, int flag = 0);
|
||||
bool hasNestedArgs(Objects *tiargs);
|
||||
void declareParameters(Scope *sc);
|
||||
int hasNestedArgs(Objects *tiargs);
|
||||
Identifier *genIdent(Objects *args);
|
||||
void expandMembers(Scope *sc);
|
||||
void tryExpandMembers(Scope *sc);
|
||||
@@ -359,8 +380,9 @@ struct TemplateInstance : ScopeDsymbol
|
||||
#endif
|
||||
};
|
||||
|
||||
struct TemplateMixin : TemplateInstance
|
||||
class TemplateMixin : public TemplateInstance
|
||||
{
|
||||
public:
|
||||
TypeQualified *tqual;
|
||||
|
||||
TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs);
|
||||
@@ -370,9 +392,9 @@ struct TemplateMixin : TemplateInstance
|
||||
void semantic3(Scope *sc);
|
||||
void inlineScan();
|
||||
const char *kind();
|
||||
int oneMember(Dsymbol **ps, Identifier *ident);
|
||||
bool oneMember(Dsymbol **ps, Identifier *ident);
|
||||
int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||
int hasPointers();
|
||||
bool hasPointers();
|
||||
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||
char *toChars();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -382,6 +404,8 @@ struct TemplateMixin : TemplateInstance
|
||||
void toObjFile(int multiobj); // compile to .obj file
|
||||
#endif
|
||||
|
||||
bool findTemplateDeclaration(Scope *sc);
|
||||
|
||||
TemplateMixin *isTemplateMixin() { return this; }
|
||||
|
||||
#if IN_LLVM
|
||||
@@ -389,17 +413,17 @@ struct TemplateMixin : TemplateInstance
|
||||
#endif
|
||||
};
|
||||
|
||||
Expression *isExpression(Object *o);
|
||||
Dsymbol *isDsymbol(Object *o);
|
||||
Type *isType(Object *o);
|
||||
Tuple *isTuple(Object *o);
|
||||
Parameter *isParameter(Object *o);
|
||||
Expression *isExpression(RootObject *o);
|
||||
Dsymbol *isDsymbol(RootObject *o);
|
||||
Type *isType(RootObject *o);
|
||||
Tuple *isTuple(RootObject *o);
|
||||
Parameter *isParameter(RootObject *o);
|
||||
int arrayObjectIsError(Objects *args);
|
||||
int isError(Object *o);
|
||||
Type *getType(Object *o);
|
||||
Dsymbol *getDsymbol(Object *o);
|
||||
int isError(RootObject *o);
|
||||
Type *getType(RootObject *o);
|
||||
Dsymbol *getDsymbol(RootObject *o);
|
||||
|
||||
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg);
|
||||
Object *objectSyntaxCopy(Object *o);
|
||||
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, RootObject *oarg);
|
||||
RootObject *objectSyntaxCopy(RootObject *o);
|
||||
|
||||
#endif /* DMD_TEMPLATE_H */
|
||||
|
||||
+163
-35
@@ -15,6 +15,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "rmem.h"
|
||||
#include "aav.h"
|
||||
|
||||
//#include "port.h"
|
||||
#include "mtype.h"
|
||||
@@ -51,9 +52,13 @@ struct Ptrait
|
||||
Identifier *ident; // which trait we're looking for
|
||||
};
|
||||
|
||||
static int fptraits(void *param, FuncDeclaration *f)
|
||||
{ Ptrait *p = (Ptrait *)param;
|
||||
static int fptraits(void *param, Dsymbol *s)
|
||||
{
|
||||
FuncDeclaration *f = s->isFuncDeclaration();
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
Ptrait *p = (Ptrait *)param;
|
||||
if (p->ident == Id::getVirtualFunctions && !f->isVirtual())
|
||||
return 0;
|
||||
|
||||
@@ -71,6 +76,52 @@ static int fptraits(void *param, FuncDeclaration *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all unit test functions from the given array of symbols.
|
||||
*
|
||||
* This is a helper function used by the implementation of __traits(getUnitTests).
|
||||
*
|
||||
* Input:
|
||||
* symbols array of symbols to collect the functions from
|
||||
* uniqueUnitTests an associative array (should actually be a set) to
|
||||
* keep track of already collected functions. We're
|
||||
* using an AA here to avoid doing a linear search of unitTests
|
||||
*
|
||||
* Output:
|
||||
* unitTests array of DsymbolExp's of the collected unit test functions
|
||||
* uniqueUnitTests updated with symbols from unitTests[ ]
|
||||
*/
|
||||
static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions *unitTests)
|
||||
{
|
||||
for (size_t i = 0; i < symbols->dim; i++)
|
||||
{
|
||||
Dsymbol *symbol = (*symbols)[i];
|
||||
UnitTestDeclaration *unitTest = symbol->isUnitTestDeclaration();
|
||||
if (unitTest)
|
||||
{
|
||||
if (!_aaGetRvalue(uniqueUnitTests, unitTest))
|
||||
{
|
||||
FuncAliasDeclaration* alias = new FuncAliasDeclaration(unitTest, 0);
|
||||
alias->protection = unitTest->protection;
|
||||
Expression* e = new DsymbolExp(Loc(), alias);
|
||||
unitTests->push(e);
|
||||
bool* value = (bool*) _aaGet(&uniqueUnitTests, unitTest);
|
||||
*value = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AttribDeclaration *attrDecl = symbol->isAttribDeclaration();
|
||||
|
||||
if (attrDecl)
|
||||
{
|
||||
Dsymbols *decl = attrDecl->include(NULL, NULL);
|
||||
collectUnitTests(decl, uniqueUnitTests, unitTests);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************ TraitsExp ************************************/
|
||||
|
||||
Expression *TraitsExp::semantic(Scope *sc)
|
||||
@@ -79,7 +130,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
printf("TraitsExp::semantic() %s\n", toChars());
|
||||
#endif
|
||||
if (ident != Id::compiles && ident != Id::isSame &&
|
||||
ident != Id::identifier)
|
||||
ident != Id::identifier && ident != Id::getProtection)
|
||||
{
|
||||
TemplateInstance::semanticTiargs(loc, sc, args, 1);
|
||||
}
|
||||
@@ -152,7 +203,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Type *t = isType(o);
|
||||
StructDeclaration *sd;
|
||||
if (!t)
|
||||
@@ -174,7 +225,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
AggregateDeclaration *a;
|
||||
FuncDeclaration *f;
|
||||
@@ -216,7 +267,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
else if (ident == Id::isFinalFunction)
|
||||
{
|
||||
FuncDeclaration *f;
|
||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
|
||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinalFunc())
|
||||
}
|
||||
#if DMDV2
|
||||
else if (ident == Id::isStaticFunction)
|
||||
@@ -247,7 +298,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Parameter *po = isParameter(o);
|
||||
Identifier *id;
|
||||
if (po)
|
||||
@@ -271,7 +322,13 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
|
||||
Scope *sc2 = sc->push();
|
||||
sc2->flags = sc->flags | SCOPEnoaccesscheck;
|
||||
TemplateInstance::semanticTiargs(loc, sc2, args, 1);
|
||||
sc2->pop();
|
||||
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
if (!s)
|
||||
{
|
||||
@@ -279,7 +336,8 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
error("argument %s has no protection", o->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
|
||||
if (s->scope)
|
||||
s->semantic(s->scope);
|
||||
PROT protection = s->prot();
|
||||
|
||||
const char *protName = Pprotectionnames[protection];
|
||||
@@ -292,7 +350,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
if (s)
|
||||
{
|
||||
@@ -317,7 +375,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 2)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Expression *e = isExpression((*args)[1]);
|
||||
if (!e)
|
||||
{ error("expression expected as second argument of __traits %s", ident->toChars());
|
||||
@@ -410,7 +468,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
p.exps = exps;
|
||||
p.e1 = e;
|
||||
p.ident = ident;
|
||||
overloadApply(f, &fptraits, &p);
|
||||
overloadApply(f, &p, &fptraits);
|
||||
|
||||
TupleExp *tup = new TupleExp(loc, exps);
|
||||
return tup->semantic(sc);
|
||||
@@ -422,7 +480,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
ClassDeclaration *cd;
|
||||
if (!s || (cd = s->isClassDeclaration()) == NULL)
|
||||
@@ -436,7 +494,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
if (!s)
|
||||
{
|
||||
@@ -459,7 +517,7 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
Object *o = (*args)[0];
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
ScopeDsymbol *sd;
|
||||
if (!s)
|
||||
@@ -488,6 +546,14 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
//printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
|
||||
if (sm->ident)
|
||||
{
|
||||
if (sm->ident != Id::ctor && // backword compatibility
|
||||
sm->ident != Id::dtor && // backword compatibility
|
||||
sm->ident != Id::_postblit && // backword compatibility
|
||||
memcmp(sm->ident->string, "__", 2) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//printf("\t%s\n", sm->ident->toChars());
|
||||
Identifiers *idents = (Identifiers *)ctx;
|
||||
|
||||
@@ -570,37 +636,42 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
goto Lfalse;
|
||||
|
||||
for (size_t i = 0; i < dim; i++)
|
||||
{ Object *o = (*args)[i];
|
||||
Expression *e;
|
||||
|
||||
{
|
||||
unsigned errors = global.startGagging();
|
||||
unsigned oldspec = global.speculativeGag;
|
||||
global.speculativeGag = global.gag;
|
||||
bool scSpec = sc->speculative;
|
||||
sc = sc->push();
|
||||
sc->speculative = true;
|
||||
sc->flags = sc->enclosing->flags & ~SCOPEctfe; // inherit without CTFEing
|
||||
bool err = false;
|
||||
|
||||
RootObject *o = (*args)[i];
|
||||
Type *t = isType(o);
|
||||
if (t)
|
||||
{ Dsymbol *s;
|
||||
Expression *e = t ? t->toExpression() : isExpression(o);
|
||||
if (!e && t)
|
||||
{
|
||||
Dsymbol *s;
|
||||
t->resolve(loc, sc, &e, &t, &s);
|
||||
if (t)
|
||||
{
|
||||
t->semantic(loc, sc);
|
||||
else if (e)
|
||||
{ e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue);
|
||||
if (t->ty == Terror)
|
||||
err = true;
|
||||
}
|
||||
else if (s && s->errors)
|
||||
err = true;
|
||||
}
|
||||
else
|
||||
{ e = isExpression(o);
|
||||
if (e)
|
||||
{ e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue);
|
||||
}
|
||||
if (e)
|
||||
{
|
||||
e = e->semantic(sc);
|
||||
e = e->optimize(WANTvalue);
|
||||
if (e->op == TOKerror)
|
||||
err = true;
|
||||
}
|
||||
|
||||
sc->speculative = scSpec;
|
||||
sc = sc->pop();
|
||||
global.speculativeGag = oldspec;
|
||||
if (global.endGagging(errors))
|
||||
if (global.endGagging(errors) || err)
|
||||
{
|
||||
goto Lfalse;
|
||||
}
|
||||
@@ -613,8 +684,8 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
if (dim != 2)
|
||||
goto Ldimerror;
|
||||
TemplateInstance::semanticTiargs(loc, sc, args, 0);
|
||||
Object *o1 = (*args)[0];
|
||||
Object *o2 = (*args)[1];
|
||||
RootObject *o1 = (*args)[0];
|
||||
RootObject *o2 = (*args)[1];
|
||||
Dsymbol *s1 = getDsymbol(o1);
|
||||
Dsymbol *s2 = getDsymbol(o2);
|
||||
|
||||
@@ -660,6 +731,64 @@ Expression *TraitsExp::semantic(Scope *sc)
|
||||
else
|
||||
goto Lfalse;
|
||||
}
|
||||
else if (ident == Id::getUnitTests)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
if (!s)
|
||||
{
|
||||
error("argument %s to __traits(getUnitTests) must be a module or aggregate", o->toChars());
|
||||
goto Lfalse;
|
||||
}
|
||||
|
||||
Import *imp = s->isImport();
|
||||
if (imp) // Bugzilla 10990
|
||||
s = imp->mod;
|
||||
|
||||
ScopeDsymbol* scope = s->isScopeDsymbol();
|
||||
|
||||
if (!scope)
|
||||
{
|
||||
error("argument %s to __traits(getUnitTests) must be a module or aggregate, not a %s", s->toChars(), s->kind());
|
||||
goto Lfalse;
|
||||
}
|
||||
|
||||
Expressions* unitTests = new Expressions();
|
||||
Dsymbols* symbols = scope->members;
|
||||
|
||||
if (global.params.useUnitTests && symbols)
|
||||
{
|
||||
// Should actually be a set
|
||||
AA* uniqueUnitTests = NULL;
|
||||
collectUnitTests(symbols, uniqueUnitTests, unitTests);
|
||||
}
|
||||
|
||||
TupleExp *tup = new TupleExp(loc, unitTests);
|
||||
return tup->semantic(sc);
|
||||
}
|
||||
else if (ident == Id::isOverrideFunction)
|
||||
{
|
||||
FuncDeclaration *f;
|
||||
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isOverride())
|
||||
}
|
||||
else if(ident == Id::getVirtualIndex)
|
||||
{
|
||||
if (dim != 1)
|
||||
goto Ldimerror;
|
||||
RootObject *o = (*args)[0];
|
||||
Dsymbol *s = getDsymbol(o);
|
||||
FuncDeclaration *fd;
|
||||
if (!s || (fd = s->isFuncDeclaration()) == NULL)
|
||||
{
|
||||
error("first argument to __traits(getVirtualIndex) must be a function");
|
||||
goto Lfalse;
|
||||
}
|
||||
fd = fd->toAliasFunc(); // Neccessary to support multiple overloads.
|
||||
ptrdiff_t result = fd->isVirtual() ? fd->vtblIndex : -1;
|
||||
return new IntegerExp(loc, fd->vtblIndex, Type::tptrdiff_t);
|
||||
}
|
||||
else
|
||||
{ error("unrecognized trait %s", ident->toChars());
|
||||
goto Lfalse;
|
||||
@@ -679,5 +808,4 @@ Ltrue:
|
||||
return new IntegerExp(loc, 1, Type::tbool);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,11 +57,17 @@ int DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
if (ident)
|
||||
{
|
||||
if (!m)
|
||||
{
|
||||
error("declaration must be at module level");
|
||||
errors = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (findCondition(m->debugidsNot, ident))
|
||||
{
|
||||
error("defined after use");
|
||||
errors = true;
|
||||
}
|
||||
if (!m->debugids)
|
||||
m->debugids = new Strings();
|
||||
m->debugids->push(ident->toChars());
|
||||
@@ -70,7 +76,10 @@ int DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
else
|
||||
{
|
||||
if (!m)
|
||||
{
|
||||
error("level declaration must be at module level");
|
||||
errors = true;
|
||||
}
|
||||
else
|
||||
m->debuglevel = level;
|
||||
}
|
||||
@@ -138,11 +147,17 @@ int VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
{
|
||||
VersionCondition::checkPredefined(loc, ident->toChars());
|
||||
if (!m)
|
||||
{
|
||||
error("declaration must be at module level");
|
||||
errors = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (findCondition(m->versionidsNot, ident))
|
||||
{
|
||||
error("defined after use");
|
||||
errors = true;
|
||||
}
|
||||
if (!m->versionids)
|
||||
m->versionids = new Strings();
|
||||
m->versionids->push(ident->toChars());
|
||||
@@ -151,7 +166,10 @@ int VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||
else
|
||||
{
|
||||
if (!m)
|
||||
{
|
||||
error("level declaration must be at module level");
|
||||
errors = true;
|
||||
}
|
||||
else
|
||||
m->versionlevel = level;
|
||||
}
|
||||
|
||||
+4
-2
@@ -20,8 +20,9 @@
|
||||
struct OutBuffer;
|
||||
struct HdrGenState;
|
||||
|
||||
struct DebugSymbol : Dsymbol
|
||||
class DebugSymbol : public Dsymbol
|
||||
{
|
||||
public:
|
||||
unsigned level;
|
||||
|
||||
DebugSymbol(Loc loc, Identifier *ident);
|
||||
@@ -34,8 +35,9 @@ struct DebugSymbol : Dsymbol
|
||||
const char *kind();
|
||||
};
|
||||
|
||||
struct VersionSymbol : Dsymbol
|
||||
class VersionSymbol : public Dsymbol
|
||||
{
|
||||
public:
|
||||
unsigned level;
|
||||
|
||||
VersionSymbol(Loc loc, Identifier *ident);
|
||||
|
||||
Reference in New Issue
Block a user