First merge of 2.064 beta.

This corresponds to DMD commit a913ce4bc59a94a022a27e390fc841f4aededffb.

Doesn't build Phobos yet.
This commit is contained in:
David Nadlinger
2013-10-29 19:21:15 +01:00
committed by Kai Nacke
parent c400d180d2
commit cb341586e3
130 changed files with 13566 additions and 9190 deletions
+58 -18
View File
@@ -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
View File
@@ -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
View File
@@ -22,8 +22,9 @@
#if DMDV2
struct AliasThis : Dsymbol
class AliasThis : public Dsymbol
{
public:
// alias Identifier this;
Identifier *ident;
+18 -20
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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(&macrotable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p));
Macro::define(&macrotable, (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(&macrotable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p));
Macro::define(&macrotable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
Macro::define(&macrotable, (utf8_t *)"DATETIME", 8, (utf8_t *)p, strlen(p));
Macro::define(&macrotable, (utf8_t *)"YEAR", 4, (utf8_t *)p + 20, 4);
}
char *srcfilename = srcfile->toChars();
Macro::define(&macrotable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename));
Macro::define(&macrotable, (utf8_t *)"SRCFILENAME", 11, (utf8_t *)srcfilename, strlen(srcfilename));
char *docfilename = docfile->toChars();
Macro::define(&macrotable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
Macro::define(&macrotable, (utf8_t *)"DOCFILENAME", 11, (utf8_t *)docfilename, strlen(docfilename));
if (dc->copyright)
{
dc->copyright->nooutput = 1;
Macro::define(&macrotable, (unsigned char *)"COPYRIGHT", 9, dc->copyright->body, dc->copyright->bodylen);
Macro::define(&macrotable, (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(&macrotable, (unsigned char *)"BODY", 4, buf.data, buf.offset);
Macro::define(&macrotable, (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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+295 -197
View File
File diff suppressed because it is too large Load Diff
+599 -615
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+19 -24
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
File diff suppressed because it is too large Load Diff
+98 -68
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+41 -40
View File
@@ -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
View File
@@ -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;
}
}
-222
View File
@@ -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;
}
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+165 -77
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+114 -90
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// Copyright (c) 1999-2013 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -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
View File
@@ -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
+18
View File
@@ -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
View File
@@ -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);