Merge the 2.063 frontend.

This commit is contained in:
David Nadlinger
2013-06-12 20:16:37 +02:00
parent 981a6af17e
commit 292caa1438
90 changed files with 10179 additions and 8105 deletions
+28 -27
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,6 +18,7 @@
#include "root.h"
#include "dsymbol.h"
#include "declaration.h"
#if IN_LLVM
#include <vector>
@@ -74,18 +75,25 @@ struct AggregateDeclaration : ScopeDsymbol
bool isdeprecated; // !=0 if deprecated
#if DMDV2
bool isnested; // !=0 if is nested
Dsymbol *enclosing; /* !=NULL if is nested
* pointing to the dsymbol that directly enclosing it.
* 1. The function that enclosing it (nested struct and class)
* 2. The class that enclosing it (nested class only)
* 3. If enclosing aggregate is template, its enclosing dsymbol.
* See AggregateDeclaraton::makeNested for the details.
*/
VarDeclaration *vthis; // 'this' parameter if this aggregate is nested
#endif
// Special member functions
InvariantDeclaration *inv; // invariant
FuncDeclarations invs; // Array of invariants
FuncDeclaration *inv; // invariant
NewDeclaration *aggNew; // allocator
DeleteDeclaration *aggDelete; // deallocator
#if DMDV2
//CtorDeclaration *ctor;
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
CtorDeclaration *defaultCtor; // default constructor
CtorDeclaration *defaultCtor; // default constructor - should have no arguments, because
// it would be stored in TypeInfo_Class.defaultConstructor
Dsymbol *aliasthis; // forward unresolved lookups to aliasthis
bool noDefaultCtor; // no default construction
#endif
@@ -93,10 +101,6 @@ struct AggregateDeclaration : ScopeDsymbol
FuncDeclarations dtors; // Array of destructors
FuncDeclaration *dtor; // aggregate destructor
#ifdef IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this)
AggregateDeclaration(Loc loc, Identifier *id);
@@ -112,18 +116,21 @@ struct AggregateDeclaration : ScopeDsymbol
Type *getType();
int firstFieldInUnion(int indx); // first field in union that includes indx
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
int isDeprecated(); // is aggregate deprecated?
bool isDeprecated(); // is aggregate deprecated?
FuncDeclaration *buildDtor(Scope *sc);
int isNested();
FuncDeclaration *buildInv(Scope *sc);
bool isNested();
void makeNested();
int isExport();
void emitComment(Scope *sc);
void toJson(JsonOut *json);
void toDocBuffer(OutBuffer *buf, Scope *sc);
FuncDeclaration *hasIdentityOpAssign(Scope *sc, Dsymbol *assign);
FuncDeclaration *hasIdentityOpAssign(Scope *sc);
FuncDeclaration *hasIdentityOpEquals(Scope *sc);
char *mangle(bool isv = false);
const char *mangle(bool isv = false);
// For access checking
virtual PROT getAccess(Dsymbol *smember); // determine access to smember
@@ -173,7 +180,7 @@ struct StructDeclaration : AggregateDeclaration
void semantic(Scope *sc);
Dsymbol *search(Loc, Identifier *ident, int flags);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle(bool isv = false);
const char *mangle(bool isv = false);
const char *kind();
void finalizeSize(Scope *sc);
bool isPOD();
@@ -184,12 +191,10 @@ struct StructDeclaration : AggregateDeclaration
int needOpAssign();
int needOpEquals();
FuncDeclaration *buildOpAssign(Scope *sc);
FuncDeclaration *buildOpEquals(Scope *sc);
FuncDeclaration *buildPostBlit(Scope *sc);
FuncDeclaration *buildCpCtor(Scope *sc);
FuncDeclaration *buildOpEquals(Scope *sc);
FuncDeclaration *buildXopEquals(Scope *sc);
void makeNested();
#endif
void toDocBuffer(OutBuffer *buf, Scope *sc);
@@ -276,13 +281,12 @@ 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)
int isscope; // !=0 if this is an auto class
int isscope; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
#if DMDV1
bool isnested; // !=0 if is nested
VarDeclaration *vthis; // 'this' parameter if this class is nested
#endif
int inuse; // to prevent recursive attempts
enum 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);
Dsymbol *syntaxCopy(Dsymbol *s);
@@ -295,15 +299,12 @@ struct ClassDeclaration : AggregateDeclaration
virtual int isBaseInfoComplete();
Dsymbol *search(Loc, Identifier *ident, int flags);
Dsymbol *searchBase(Loc, Identifier *ident);
ClassDeclaration *searchBase(Loc, Identifier *ident);
#if DMDV2
int isFuncHidden(FuncDeclaration *fd);
#endif
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc);
#if DMDV1
int isNested();
#endif
int isCOMclass();
virtual int isCOMinterface();
#if DMDV2
@@ -312,7 +313,7 @@ struct ClassDeclaration : AggregateDeclaration
int isAbstract();
virtual int vtblOffset();
const char *kind();
char *mangle(bool isv = false);
const char *mangle(bool isv = false);
void toDocBuffer(OutBuffer *buf, Scope *sc);
PROT getAccess(Dsymbol *smember); // determine access to smember
+15 -1
View File
@@ -36,8 +36,22 @@ Expression *resolveAliasThis(Scope *sc, Expression *e)
L1:
if (ad && ad->aliasthis)
{
bool isstatic = (e->op == TOKtype);
e = new DotIdExp(e->loc, e, ad->aliasthis->ident);
e = e->semantic(sc);
if (isstatic && ad->aliasthis->needThis())
{
/* non-@property function is not called inside typeof(),
* so resolve it ahead.
*/
int save = sc->intypeof;
sc->intypeof = 1; // bypass "need this" error check
e = resolveProperties(sc, e);
sc->intypeof = save;
e = new TypeExp(e->loc, new TypeTypeof(e->loc, e));
e = e->semantic(sc);
}
e = resolveProperties(sc, e);
}
}
@@ -74,7 +88,7 @@ void AliasThis::semantic(Scope *sc)
assert(ad->members);
Dsymbol *s = ad->search(loc, ident, 0);
if (!s)
{ s = sc->search(loc, ident, 0);
{ s = sc->search(loc, ident, NULL);
if (s)
::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
else
+9 -8
View File
@@ -36,12 +36,7 @@ int Expression::apply(fp_t fp, void *param)
/******************************
* Perform apply() on an t if not null
*/
template<typename T>
int condApply(T* t, fp_t fp, void* param)
{
return t ? t->apply(fp, param) : 0;
}
#define condApply(t, fp, param) (t ? t->apply(fp, param) : 0)
int NewExp::apply(int (*fp)(Expression *, void *), void *param)
{
@@ -129,14 +124,20 @@ int AssocArrayLiteralExp::apply(fp_t fp, void *param)
int StructLiteralExp::apply(fp_t fp, void *param)
{
return condApply(elements, fp, param) ||
if(stageflags & stageApply) return 0;
int old = stageflags;
stageflags |= stageApply;
int ret = condApply(elements, fp, param) ||
(*fp)(this, param);
stageflags = old;
return ret;
}
int TupleExp::apply(fp_t fp, void *param)
{
return condApply(exps, fp, param) ||
return (e0 ? (*fp)(e0, param) : 0) ||
condApply(exps, fp, param) ||
(*fp)(this, param);
}
+6 -9
View File
@@ -26,9 +26,6 @@
#include "aggregate.h"
#include "hdrgen.h"
#define tfloat2 tfloat64
//#define tfloat2 tcomplex32
/****************************************************
* This breaks a type down into 'simpler' types that can be passed to a function
* in registers, and returned in registers.
@@ -84,7 +81,7 @@ TypeTuple *TypeBasic::toArgTypes()
case Tcomplex32:
if (global.params.is64bit)
t1 = Type::tfloat2;
t1 = Type::tfloat64;
else
{
t1 = Type::tfloat64;
@@ -223,8 +220,8 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2)
if (!t2)
return t1;
unsigned sz1 = t1->size(0);
unsigned sz2 = t2->size(0);
unsigned sz1 = t1->size(Loc());
unsigned sz2 = t2->size(Loc());
if (t1->ty != t2->ty &&
(t1->ty == Tfloat80 || t2->ty == Tfloat80))
@@ -232,7 +229,7 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2)
// [float,float] => [cfloat]
if (t1->ty == Tfloat32 && t2->ty == Tfloat32 && offset2 == 4)
return Type::tfloat2;
return Type::tfloat64;
// Merging floating and non-floating types produces the non-floating type
if (t1->isfloating())
@@ -287,7 +284,7 @@ TypeTuple *TypeStruct::toArgTypes()
}
Type *t1 = NULL;
Type *t2 = NULL;
d_uns64 sz = size(0);
d_uns64 sz = size(Loc());
assert(sz < 0xFFFFFFFF);
switch ((unsigned)sz)
{
@@ -349,7 +346,7 @@ TypeTuple *TypeStruct::toArgTypes()
goto Lmemory;
// Fields that overlap the 8byte boundary goto Lmemory
unsigned fieldsz = f->type->size(0);
unsigned fieldsz = f->type->size(Loc());
if (f->offset < 8 && (f->offset + fieldsz) > 8)
goto Lmemory;
}
+293 -266
View File
@@ -52,6 +52,280 @@ int binary(const char *p , const char **tab, int high)
}
#endif
/**************************************
* Structure to contain information needed to insert an array op call
*/
struct ArrayOp
{
FuncDeclaration *cFunc; // Stub for optimized druntime version
FuncDeclaration *dFunc; // Full D version for ctfe
};
/**************************************
* Search for a druntime array op
*/
int isDruntimeArrayOp(Identifier *ident)
{
/* Some of the array op functions are written as library functions,
* presumably to optimize them with special CPU vector instructions.
* List those library functions here, in alpha order.
*/
static const char *libArrayopFuncs[] =
{
"_arrayExpSliceAddass_a",
"_arrayExpSliceAddass_d", // T[]+=T
"_arrayExpSliceAddass_f", // T[]+=T
"_arrayExpSliceAddass_g",
"_arrayExpSliceAddass_h",
"_arrayExpSliceAddass_i",
"_arrayExpSliceAddass_k",
"_arrayExpSliceAddass_s",
"_arrayExpSliceAddass_t",
"_arrayExpSliceAddass_u",
"_arrayExpSliceAddass_w",
"_arrayExpSliceDivass_d", // T[]/=T
"_arrayExpSliceDivass_f", // T[]/=T
"_arrayExpSliceMinSliceAssign_a",
"_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_g",
"_arrayExpSliceMinSliceAssign_h",
"_arrayExpSliceMinSliceAssign_i",
"_arrayExpSliceMinSliceAssign_k",
"_arrayExpSliceMinSliceAssign_s",
"_arrayExpSliceMinSliceAssign_t",
"_arrayExpSliceMinSliceAssign_u",
"_arrayExpSliceMinSliceAssign_w",
"_arrayExpSliceMinass_a",
"_arrayExpSliceMinass_d", // T[]-=T
"_arrayExpSliceMinass_f", // T[]-=T
"_arrayExpSliceMinass_g",
"_arrayExpSliceMinass_h",
"_arrayExpSliceMinass_i",
"_arrayExpSliceMinass_k",
"_arrayExpSliceMinass_s",
"_arrayExpSliceMinass_t",
"_arrayExpSliceMinass_u",
"_arrayExpSliceMinass_w",
"_arrayExpSliceMulass_d", // T[]*=T
"_arrayExpSliceMulass_f", // T[]*=T
"_arrayExpSliceMulass_i",
"_arrayExpSliceMulass_k",
"_arrayExpSliceMulass_s",
"_arrayExpSliceMulass_t",
"_arrayExpSliceMulass_u",
"_arrayExpSliceMulass_w",
"_arraySliceExpAddSliceAssign_a",
"_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_g",
"_arraySliceExpAddSliceAssign_h",
"_arraySliceExpAddSliceAssign_i",
"_arraySliceExpAddSliceAssign_k",
"_arraySliceExpAddSliceAssign_s",
"_arraySliceExpAddSliceAssign_t",
"_arraySliceExpAddSliceAssign_u",
"_arraySliceExpAddSliceAssign_w",
"_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
"_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
"_arraySliceExpMinSliceAssign_a",
"_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_g",
"_arraySliceExpMinSliceAssign_h",
"_arraySliceExpMinSliceAssign_i",
"_arraySliceExpMinSliceAssign_k",
"_arraySliceExpMinSliceAssign_s",
"_arraySliceExpMinSliceAssign_t",
"_arraySliceExpMinSliceAssign_u",
"_arraySliceExpMinSliceAssign_w",
"_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
"_arraySliceExpMulSliceAddass_f",
"_arraySliceExpMulSliceAddass_r",
"_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_i",
"_arraySliceExpMulSliceAssign_k",
"_arraySliceExpMulSliceAssign_s",
"_arraySliceExpMulSliceAssign_t",
"_arraySliceExpMulSliceAssign_u",
"_arraySliceExpMulSliceAssign_w",
"_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
"_arraySliceExpMulSliceMinass_f",
"_arraySliceExpMulSliceMinass_r",
"_arraySliceSliceAddSliceAssign_a",
"_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_g",
"_arraySliceSliceAddSliceAssign_h",
"_arraySliceSliceAddSliceAssign_i",
"_arraySliceSliceAddSliceAssign_k",
"_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_s",
"_arraySliceSliceAddSliceAssign_t",
"_arraySliceSliceAddSliceAssign_u",
"_arraySliceSliceAddSliceAssign_w",
"_arraySliceSliceAddass_a",
"_arraySliceSliceAddass_d", // T[]+=T[]
"_arraySliceSliceAddass_f", // T[]+=T[]
"_arraySliceSliceAddass_g",
"_arraySliceSliceAddass_h",
"_arraySliceSliceAddass_i",
"_arraySliceSliceAddass_k",
"_arraySliceSliceAddass_s",
"_arraySliceSliceAddass_t",
"_arraySliceSliceAddass_u",
"_arraySliceSliceAddass_w",
"_arraySliceSliceMinSliceAssign_a",
"_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_g",
"_arraySliceSliceMinSliceAssign_h",
"_arraySliceSliceMinSliceAssign_i",
"_arraySliceSliceMinSliceAssign_k",
"_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_s",
"_arraySliceSliceMinSliceAssign_t",
"_arraySliceSliceMinSliceAssign_u",
"_arraySliceSliceMinSliceAssign_w",
"_arraySliceSliceMinass_a",
"_arraySliceSliceMinass_d", // T[]-=T[]
"_arraySliceSliceMinass_f", // T[]-=T[]
"_arraySliceSliceMinass_g",
"_arraySliceSliceMinass_h",
"_arraySliceSliceMinass_i",
"_arraySliceSliceMinass_k",
"_arraySliceSliceMinass_s",
"_arraySliceSliceMinass_t",
"_arraySliceSliceMinass_u",
"_arraySliceSliceMinass_w",
"_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_i",
"_arraySliceSliceMulSliceAssign_k",
"_arraySliceSliceMulSliceAssign_s",
"_arraySliceSliceMulSliceAssign_t",
"_arraySliceSliceMulSliceAssign_u",
"_arraySliceSliceMulSliceAssign_w",
"_arraySliceSliceMulass_d", // T[]*=T[]
"_arraySliceSliceMulass_f", // T[]*=T[]
"_arraySliceSliceMulass_i",
"_arraySliceSliceMulass_k",
"_arraySliceSliceMulass_s",
"_arraySliceSliceMulass_t",
"_arraySliceSliceMulass_u",
"_arraySliceSliceMulass_w",
};
char *name = ident->toChars();
int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
if (i != -1)
return 1;
#ifdef DEBUG // Make sure our array is alphabetized
for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
{
if (strcmp(name, libArrayopFuncs[i]) == 0)
assert(0);
}
#endif
return 0;
}
ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc)
{
ArrayOp *op = new ArrayOp;
#if IN_LLVM
Parameters *fparams = new Parameters();
Expression *loopbody = exp->buildArrayLoop(fparams);
if (isDruntimeArrayOp(ident))
op->cFunc = FuncDeclaration::genCfunc(fparams, exp->type, ident);
#else
if (isDruntimeArrayOp(ident))
op->cFunc = FuncDeclaration::genCfunc(exp->type, ident);
#endif
else
op->cFunc = NULL;
/* Construct the function body:
* foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
* 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++)
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
Statement *s1 = new ForStatement(0,
new ExpStatement(0, d),
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
new ExpStatement(0, loopbody));
#else
// foreach (i; 0 .. p.length)
Statement *s1 = new ForeachRangeStatement(Loc(), TOKforeach,
new Parameter(0, NULL, Id::p, NULL),
new IntegerExp(Loc(), 0, Type::tsize_t),
new ArrayLengthExp(Loc(), new IdentifierExp(Loc(), p->ident)),
new ExpStatement(Loc(), loopbody));
#endif
//printf("%s\n", s1->toChars());
Statement *s2 = new ReturnStatement(Loc(), new IdentifierExp(Loc(), p->ident));
//printf("s2: %s\n", s2->toChars());
Statement *fbody = new CompoundStatement(Loc(), s1, s2);
/* Construct the function
*/
TypeFunction *ftype = new TypeFunction(fparams, exp->type, 0, LINKc);
//printf("ftype: %s\n", ftype->toChars());
FuncDeclaration *fd = new FuncDeclaration(Loc(), Loc(), ident, STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTpublic;
fd->linkage = LINKc;
fd->isArrayOp = 1;
if (!op->cFunc)
sc->module->importedFrom->members->push(fd);
sc = sc->push();
sc->parent = sc->module->importedFrom;
sc->stc = 0;
sc->linkage = LINKc;
fd->semantic(sc);
fd->semantic2(sc);
fd->semantic3(sc);
sc->pop();
if (op->cFunc)
{
op->cFunc->dArrayOp = fd;
op->cFunc->type = fd->type;
}
op->dFunc = fd;
return op;
}
/**********************************************
* Check that there are no uses of arrays without [].
*/
@@ -147,270 +421,23 @@ Expression *BinExp::arrayOp(Scope *sc)
char *name = buf.toChars();
Identifier *ident = Lexer::idPool(name);
/* Look up name in hash table
*/
#if IN_LLVM
FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&sc->module->arrayfuncs, ident);
ArrayOp **pOp = (ArrayOp **)_aaGet(&sc->module->arrayfuncs, ident);
#else
FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&arrayfuncs, ident);
ArrayOp **pOp = (ArrayOp **)_aaGet(&arrayfuncs, ident);
#endif
FuncDeclaration *fd = (FuncDeclaration *)*pfd;
if (!fd)
{
/* Some of the array op functions are written as library functions,
* presumably to optimize them with special CPU vector instructions.
* List those library functions here, in alpha order.
*/
static const char *libArrayopFuncs[] =
{
"_arrayExpSliceAddass_a",
"_arrayExpSliceAddass_d", // T[]+=T
"_arrayExpSliceAddass_f", // T[]+=T
"_arrayExpSliceAddass_g",
"_arrayExpSliceAddass_h",
"_arrayExpSliceAddass_i",
"_arrayExpSliceAddass_k",
"_arrayExpSliceAddass_s",
"_arrayExpSliceAddass_t",
"_arrayExpSliceAddass_u",
"_arrayExpSliceAddass_w",
ArrayOp *op = *pOp;
"_arrayExpSliceDivass_d", // T[]/=T
"_arrayExpSliceDivass_f", // T[]/=T
if (!op)
op = buildArrayOp(ident, this, sc, loc);
"_arrayExpSliceMinSliceAssign_a",
"_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
"_arrayExpSliceMinSliceAssign_g",
"_arrayExpSliceMinSliceAssign_h",
"_arrayExpSliceMinSliceAssign_i",
"_arrayExpSliceMinSliceAssign_k",
"_arrayExpSliceMinSliceAssign_s",
"_arrayExpSliceMinSliceAssign_t",
"_arrayExpSliceMinSliceAssign_u",
"_arrayExpSliceMinSliceAssign_w",
*pOp = op;
"_arrayExpSliceMinass_a",
"_arrayExpSliceMinass_d", // T[]-=T
"_arrayExpSliceMinass_f", // T[]-=T
"_arrayExpSliceMinass_g",
"_arrayExpSliceMinass_h",
"_arrayExpSliceMinass_i",
"_arrayExpSliceMinass_k",
"_arrayExpSliceMinass_s",
"_arrayExpSliceMinass_t",
"_arrayExpSliceMinass_u",
"_arrayExpSliceMinass_w",
"_arrayExpSliceMulass_d", // T[]*=T
"_arrayExpSliceMulass_f", // T[]*=T
"_arrayExpSliceMulass_i",
"_arrayExpSliceMulass_k",
"_arrayExpSliceMulass_s",
"_arrayExpSliceMulass_t",
"_arrayExpSliceMulass_u",
"_arrayExpSliceMulass_w",
"_arraySliceExpAddSliceAssign_a",
"_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
"_arraySliceExpAddSliceAssign_g",
"_arraySliceExpAddSliceAssign_h",
"_arraySliceExpAddSliceAssign_i",
"_arraySliceExpAddSliceAssign_k",
"_arraySliceExpAddSliceAssign_s",
"_arraySliceExpAddSliceAssign_t",
"_arraySliceExpAddSliceAssign_u",
"_arraySliceExpAddSliceAssign_w",
"_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
"_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
"_arraySliceExpMinSliceAssign_a",
"_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
"_arraySliceExpMinSliceAssign_g",
"_arraySliceExpMinSliceAssign_h",
"_arraySliceExpMinSliceAssign_i",
"_arraySliceExpMinSliceAssign_k",
"_arraySliceExpMinSliceAssign_s",
"_arraySliceExpMinSliceAssign_t",
"_arraySliceExpMinSliceAssign_u",
"_arraySliceExpMinSliceAssign_w",
"_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
"_arraySliceExpMulSliceAddass_f",
"_arraySliceExpMulSliceAddass_r",
"_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
"_arraySliceExpMulSliceAssign_i",
"_arraySliceExpMulSliceAssign_k",
"_arraySliceExpMulSliceAssign_s",
"_arraySliceExpMulSliceAssign_t",
"_arraySliceExpMulSliceAssign_u",
"_arraySliceExpMulSliceAssign_w",
"_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
"_arraySliceExpMulSliceMinass_f",
"_arraySliceExpMulSliceMinass_r",
"_arraySliceSliceAddSliceAssign_a",
"_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_g",
"_arraySliceSliceAddSliceAssign_h",
"_arraySliceSliceAddSliceAssign_i",
"_arraySliceSliceAddSliceAssign_k",
"_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
"_arraySliceSliceAddSliceAssign_s",
"_arraySliceSliceAddSliceAssign_t",
"_arraySliceSliceAddSliceAssign_u",
"_arraySliceSliceAddSliceAssign_w",
"_arraySliceSliceAddass_a",
"_arraySliceSliceAddass_d", // T[]+=T[]
"_arraySliceSliceAddass_f", // T[]+=T[]
"_arraySliceSliceAddass_g",
"_arraySliceSliceAddass_h",
"_arraySliceSliceAddass_i",
"_arraySliceSliceAddass_k",
"_arraySliceSliceAddass_s",
"_arraySliceSliceAddass_t",
"_arraySliceSliceAddass_u",
"_arraySliceSliceAddass_w",
"_arraySliceSliceMinSliceAssign_a",
"_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_g",
"_arraySliceSliceMinSliceAssign_h",
"_arraySliceSliceMinSliceAssign_i",
"_arraySliceSliceMinSliceAssign_k",
"_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
"_arraySliceSliceMinSliceAssign_s",
"_arraySliceSliceMinSliceAssign_t",
"_arraySliceSliceMinSliceAssign_u",
"_arraySliceSliceMinSliceAssign_w",
"_arraySliceSliceMinass_a",
"_arraySliceSliceMinass_d", // T[]-=T[]
"_arraySliceSliceMinass_f", // T[]-=T[]
"_arraySliceSliceMinass_g",
"_arraySliceSliceMinass_h",
"_arraySliceSliceMinass_i",
"_arraySliceSliceMinass_k",
"_arraySliceSliceMinass_s",
"_arraySliceSliceMinass_t",
"_arraySliceSliceMinass_u",
"_arraySliceSliceMinass_w",
"_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
"_arraySliceSliceMulSliceAssign_i",
"_arraySliceSliceMulSliceAssign_k",
"_arraySliceSliceMulSliceAssign_s",
"_arraySliceSliceMulSliceAssign_t",
"_arraySliceSliceMulSliceAssign_u",
"_arraySliceSliceMulSliceAssign_w",
"_arraySliceSliceMulass_d", // T[]*=T[]
"_arraySliceSliceMulass_f", // T[]*=T[]
"_arraySliceSliceMulass_i",
"_arraySliceSliceMulass_k",
"_arraySliceSliceMulass_s",
"_arraySliceSliceMulass_t",
"_arraySliceSliceMulass_u",
"_arraySliceSliceMulass_w",
};
int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
if (i == -1)
{
#ifdef DEBUG // Make sure our array is alphabetized
for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
{
if (strcmp(name, libArrayopFuncs[i]) == 0)
assert(0);
}
#endif
/* Not in library, so generate it.
* Construct the function body:
* foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
* loopbody;
* return p;
*/
Parameters *fparams = new Parameters();
Expression *loopbody = buildArrayLoop(fparams);
Parameter *p = (*fparams)[0 /*fparams->dim - 1*/];
#if DMDV1
// for (size_t i = 0; i < p.length; i++)
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
Statement *s1 = new ForStatement(0,
new ExpStatement(0, d),
new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
new ExpStatement(0, loopbody));
#else
// foreach (i; 0 .. p.length)
Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
new Parameter(0, NULL, Id::p, NULL),
new IntegerExp(0, 0, Type::tsize_t),
new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
new ExpStatement(0, loopbody));
#endif
Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
//printf("s2: %s\n", s2->toChars());
Statement *fbody = new CompoundStatement(0, s1, s2);
/* Construct the function
*/
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
//printf("ftype: %s\n", ftype->toChars());
fd = new FuncDeclaration(loc, 0, ident, STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTpublic;
fd->linkage = LINKd;
fd->isArrayOp = 1;
sc->module->importedFrom->members->push(fd);
sc = sc->push();
sc->parent = sc->module->importedFrom;
sc->stc = 0;
sc->linkage = LINKc;
fd->semantic(sc);
fd->semantic2(sc);
fd->semantic3(sc);
sc->pop();
}
#if IN_LLVM
else
{ /* In library, refer to it.
*/
Parameters *fparams = new Parameters();
buildArrayLoop(fparams);
fd = FuncDeclaration::genCfunc(fparams, type, ident);
fd->isArrayOp = 2;
}
#else
else
{ /* In library, refer to it.
*/
fd = FuncDeclaration::genCfunc(type, ident);
}
#endif
*pfd = fd; // cache symbol in hash table
}
/* Call the function fd(arguments)
*/
Expression *ec = new VarExp(0, fd);
FuncDeclaration *fd = op->cFunc ? op->cFunc : op->dFunc;
Expression *ec = new VarExp(loc, fd);
Expression *e = new CallExp(loc, ec, arguments);
e->type = type;
return e;
return e->semantic(sc);
}
Expression *BinAssignExp::arrayOp(Scope *sc)
@@ -538,7 +565,7 @@ Expression *Expression::buildArrayLoop(Parameters *fparams)
Identifier *id = Identifier::generateId("c", fparams->dim);
Parameter *param = new Parameter(0, type, id, NULL);
fparams->shift(param);
Expression *e = new IdentifierExp(0, id);
Expression *e = new IdentifierExp(Loc(), id);
return e;
}
@@ -558,11 +585,11 @@ Expression *SliceExp::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(0, id);
Expression *e = new IdentifierExp(Loc(), id);
Expressions *arguments = new Expressions();
Expression *index = new IdentifierExp(0, Id::p);
Expression *index = new IdentifierExp(Loc(), Id::p);
arguments->push(index);
e = new ArrayExp(0, e, arguments);
e = new ArrayExp(Loc(), e, arguments);
return e;
}
@@ -577,12 +604,12 @@ Expression *AssignExp::buildArrayLoop(Parameters *fparams)
* where b is a byte fails because (c + p[i]) is an int
* which cannot be implicitly cast to byte.
*/
ex2 = new CastExp(0, ex2, e1->type->nextOf());
ex2 = new CastExp(Loc(), ex2, e1->type->nextOf());
#endif
Expression *ex1 = e1->buildArrayLoop(fparams);
Parameter *param = (*fparams)[0];
param->storageClass = 0;
Expression *e = new AssignExp(0, ex1, ex2);
Expression *e = new AssignExp(Loc(), ex1, ex2);
return e;
}
@@ -616,14 +643,14 @@ X(Pow)
Expression *NegExp::buildArrayLoop(Parameters *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new NegExp(0, ex1);
Expression *e = new NegExp(Loc(), ex1);
return e;
}
Expression *ComExp::buildArrayLoop(Parameters *fparams)
{
Expression *ex1 = e1->buildArrayLoop(fparams);
Expression *e = new ComExp(0, ex1);
Expression *e = new ComExp(Loc(), ex1);
return e;
}
@@ -634,7 +661,7 @@ Expression *Str##Exp::buildArrayLoop(Parameters *fparams) \
*/ \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *e = new Str##Exp(0, ex1, ex2); \
Expression *e = new Str##Exp(Loc(), ex1, ex2); \
return e; \
}
+1
View File
@@ -76,4 +76,5 @@ typedef ArrayBase<struct block> Blocks;
typedef ArrayBase<struct Symbol> Symbols;
typedef ArrayBase<struct dt_t> Dts;
#endif
+105 -120
View File
@@ -27,15 +27,11 @@
#include "module.h"
#include "parse.h"
#include "template.h"
#include "hdrgen.h"
#if IN_LLVM
#include "../gen/pragma.h"
#endif
#if IN_DMD
extern bool obj_includelib(const char *name);
void obj_startaddress(Symbol *s);
#endif
/********************************* AttribDeclaration ****************************/
@@ -252,22 +248,6 @@ void AttribDeclaration::emitComment(Scope *sc)
}
}
#if IN_DMD
void AttribDeclaration::toObjFile(int multiobj)
{
Dsymbols *d = include(NULL, NULL);
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->toObjFile(multiobj);
}
}
}
#endif
void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
Dsymbols *d = include(NULL, NULL);
@@ -361,6 +341,10 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (decl->dim == 0)
buf->writestring("{}");
else if (hgs->hdrgen && decl->dim == 1 && (*decl)[0]->isUnitTestDeclaration())
{ // hack for bugzilla 8081
buf->writestring("{}");
}
else if (decl->dim == 1)
((*decl)[0])->toCBuffer(buf, hgs);
else
@@ -519,7 +503,7 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
{ STCnothrow, TOKnothrow },
{ STCpure, TOKpure },
{ STCref, TOKref },
{ STCtls, TOKtls },
{ STCtls },
{ STCgshared, TOKgshared },
{ STCproperty, TOKat, Id::property },
{ STCsafe, TOKat, Id::safe },
@@ -536,6 +520,9 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc)
if (stc & tbl)
{
stc &= ~tbl;
if (tbl == STCtls) // TOKtls was removed
return "__thread";
enum TOK tok = table[i].tok;
#if DMDV2
if (tok == TOKat)
@@ -560,7 +547,7 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
const char *p = stcToChars(tmp, stc);
if (!p)
break;
assert(strlen(p) < sizeof(tmp));
assert(strlen(p) < sizeof(tmp) / sizeof(tmp[0]));
buf->writestring(p);
buf->writeByte(' ');
}
@@ -984,6 +971,30 @@ void PragmaDeclaration::setScope(Scope *sc)
{
}
static unsigned setMangleOverride(Dsymbol *s, char *sym)
{
AttribDeclaration *ad = s->isAttribDeclaration();
if (ad)
{
Dsymbols *decls = ad->include(NULL, NULL);
unsigned nestedCount = 0;
if (decls && decls->dim)
for (size_t i = 0; i < decls->dim; ++i)
nestedCount += setMangleOverride((*decls)[i], sym);
return nestedCount;
}
else if (s->isFuncDeclaration() || s->isVarDeclaration())
{
s->isDeclaration()->mangleOverride = sym;
return 1;
}
else
return 0;
}
void PragmaDeclaration::semantic(Scope *sc)
{ // Should be merged with PragmaStatement
@@ -1001,7 +1012,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
if (e->op != TOKerror && e->op != TOKtype)
e = e->ctfeInterpret();
@@ -1012,12 +1023,12 @@ void PragmaDeclaration::semantic(Scope *sc)
StringExp *se = e->toString();
if (se)
{
fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
fprintf(stderr, "%.*s", (int)se->len, (char *)se->string);
}
else
fprintf(stdmsg, "%s", e->toChars());
fprintf(stderr, "%s", e->toChars());
}
fprintf(stdmsg, "\n");
fprintf(stderr, "\n");
}
goto Lnodecl;
}
@@ -1029,7 +1040,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
@@ -1049,44 +1060,6 @@ void PragmaDeclaration::semantic(Scope *sc)
}
goto Lnodecl;
}
#ifdef IN_GCC
else if (ident == Id::GNU_asm)
{
if (! args || args->dim != 2)
error("identifier and string expected for asm name");
else
{
Expression *e;
Declaration *d = NULL;
StringExp *s = NULL;
e = (*args)[0];
e = e->semantic(sc);
if (e->op == TOKvar)
{
d = ((VarExp *)e)->var;
if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
d = NULL;
}
if (!d)
error("first argument of GNU_asm must be a function or variable declaration");
e = (*args)[1];
e = e->semantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
e = e->toString();
if (e && ((StringExp *)e)->sz == 1)
s = ((StringExp *)e);
else
error("second argument of GNU_asm must be a character string");
if (d && s)
d->c_ident = Lexer::idPool((char*) s->string);
}
goto Lnodecl;
}
#endif
#if DMDV2
else if (ident == Id::startaddress)
{
@@ -1095,7 +1068,7 @@ void PragmaDeclaration::semantic(Scope *sc)
else
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
(*args)[0] = e;
@@ -1106,6 +1079,36 @@ void PragmaDeclaration::semantic(Scope *sc)
goto Lnodecl;
}
#endif
else if (ident == Id::mangle)
{
if (!args || args->dim != 1)
error("string expected for mangled name");
else
{
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->ctfeInterpret();
(*args)[0] = e;
if (e->op == TOKerror)
goto Lnodecl;
StringExp *se = e->toString();
if (!se)
{
error("string expected for mangled name, not '%s'", e->toChars());
return;
}
if (!se->len)
error("zero-length string not allowed for mangled name");
if (se->sz != 1)
error("mangled name characters can only be of type char");
}
}
#if IN_LLVM
else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone)
{
@@ -1124,11 +1127,13 @@ void PragmaDeclaration::semantic(Scope *sc)
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;
e = e->semantic(sc);
#endif
e = e->ctfeSemantic(sc);
e = resolveProperties(sc, e);
e = e->ctfeInterpret();
if (i == 0)
@@ -1137,9 +1142,11 @@ void PragmaDeclaration::semantic(Scope *sc)
printf(",");
printf("%s", e->toChars());
#if IN_LLVM
// restore error state.
global.gag--;
global.errors = errors_save;
#endif
}
if (args->dim)
printf(")");
@@ -1159,9 +1166,26 @@ Ldecl:
s->semantic(sc);
if (ident == Id::mangle)
{
StringExp *e = (*args)[0]->toString();
char *name = (char *)mem.malloc(e->len + 1);
memcpy(name, e->string, e->len);
name[e->len] = 0;
unsigned cnt = setMangleOverride(s, name);
if (cnt > 1)
error("can only apply to a single declaration");
}
#if IN_LLVM
DtoCheckPragma(this, s, llvm_internal, arg1str);
else
{
DtoCheckPragma(this, s, llvm_internal, arg1str);
}
#endif
}
}
return;
@@ -1185,51 +1209,6 @@ const char *PragmaDeclaration::kind()
return "pragma";
}
#if IN_DMD
void PragmaDeclaration::toObjFile(int multiobj)
{
if (ident == Id::lib)
{
assert(args && args->dim == 1);
Expression *e = (*args)[0];
assert(e->op == TOKstring);
StringExp *se = (StringExp *)e;
char *name = (char *)mem.malloc(se->len + 1);
memcpy(name, se->string, se->len);
name[se->len] = 0;
/* Embed the library names into the object file.
* The linker will then automatically
* search that library, too.
*/
if (!obj_includelib(name))
{
/* The format does not allow embedded library names,
* so instead append the library name to the list to be passed
* to the linker.
*/
global.params.libfiles->push(name);
}
}
#if DMDV2
else if (ident == Id::startaddress)
{
assert(args && args->dim == 1);
Expression *e = (*args)[0];
Dsymbol *sa = getDsymbol(e);
FuncDeclaration *f = sa->isFuncDeclaration();
assert(f);
Symbol *s = f->toSymbol();
obj_startaddress(s);
}
#endif
AttribDeclaration::toObjFile(multiobj);
}
#endif
void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->printf("pragma (%s", ident->toChars());
@@ -1435,7 +1414,13 @@ Dsymbols *StaticIfDeclaration::include(Scope *sc, ScopeDsymbol *sd)
if (condition->inc == 0)
{
/* Bugzilla 10101: Condition evaluation may cause self-recursive
* condition evaluation. To resolve it, temporarily save sc into scope.
*/
bool x = !scope && sc;
if (x) scope = sc;
Dsymbols *d = ConditionalDeclaration::include(sc, sd);
if (x) scope = NULL;
// Set the scopes lazily.
if (scope && d)
@@ -1558,7 +1543,7 @@ 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->semantic(sc);
exp = exp->ctfeSemantic(sc);
exp = resolveProperties(sc, exp);
exp = exp->ctfeInterpret();
StringExp *se = exp->toString();
@@ -1666,8 +1651,8 @@ Expressions *UserAttributeDeclaration::concat(Expressions *udas1, Expressions *u
* (do not append to left operand, as this is a copy-on-write operation)
*/
udas = new Expressions();
udas->push(new TupleExp(0, udas1));
udas->push(new TupleExp(0, udas2));
udas->push(new TupleExp(Loc(), udas1));
udas->push(new TupleExp(Loc(), udas2));
}
return udas;
}
@@ -1692,8 +1677,8 @@ void UserAttributeDeclaration::setScope(Scope *sc)
{
// Create a tuple that combines them
Expressions *exps = new Expressions();
exps->push(new TupleExp(0, newsc->userAttributes));
exps->push(new TupleExp(0, atts));
exps->push(new TupleExp(Loc(), newsc->userAttributes));
exps->push(new TupleExp(Loc(), atts));
newsc->userAttributes = exps;
}
}
+5 -5
View File
@@ -163,27 +163,27 @@ Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments)
{
case BUILTINsin:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sinl(arg0->toReal()), arg0->type);
e = new RealExp(Loc(), sinl(arg0->toReal()), arg0->type);
break;
case BUILTINcos:
if (arg0->op == TOKfloat64)
e = new RealExp(0, cosl(arg0->toReal()), arg0->type);
e = new RealExp(Loc(), cosl(arg0->toReal()), arg0->type);
break;
case BUILTINtan:
if (arg0->op == TOKfloat64)
e = new RealExp(0, tanl(arg0->toReal()), arg0->type);
e = new RealExp(Loc(), tanl(arg0->toReal()), arg0->type);
break;
case BUILTINsqrt:
if (arg0->op == TOKfloat64)
e = new RealExp(0, sqrtl(arg0->toReal()), arg0->type);
e = new RealExp(Loc(), sqrtl(arg0->toReal()), arg0->type);
break;
case BUILTINfabs:
if (arg0->op == TOKfloat64)
e = new RealExp(0, fabsl(arg0->toReal()), arg0->type);
e = new RealExp(Loc(), fabsl(arg0->toReal()), arg0->type);
break;
// These math intrinsics are not yet implemented
case BUILTINatan2:
+192 -21
View File
@@ -20,6 +20,7 @@
#include "aggregate.h"
#include "template.h"
#include "scope.h"
#include "id.h"
//#define DUMP .dump(__PRETTY_FUNCTION__, this)
#define DUMP
@@ -280,7 +281,11 @@ MATCH IntegerExp::implicitConvTo(Type *t)
goto Lyes;
case Tint8:
if ((signed char)value != value)
if (ty == Tuns64 && value & ~0x7FUL)
goto Lno;
//else if (ty == Tint64 && 0x7FUL < value && value < ~0x7FUL)
// goto Lno;
else if ((signed char)value != value)
goto Lno;
goto Lyes;
@@ -294,7 +299,11 @@ MATCH IntegerExp::implicitConvTo(Type *t)
goto Lyes;
case Tint16:
if ((short)value != value)
if (ty == Tuns64 && value & ~0x7FFFUL)
goto Lno;
//else if (ty == Tint64 && 0x7FFFUL < value && value < ~0x7FFFUL)
// goto Lno;
else if ((short)value != value)
goto Lno;
goto Lyes;
@@ -310,6 +319,10 @@ MATCH IntegerExp::implicitConvTo(Type *t)
if (ty == Tuns32)
{
}
else if (ty == Tuns64 && value & ~0x7FFFFFFFUL)
goto Lno;
//else if (ty == Tint64 && 0x7FFFFFFFUL < value && value < ~0x7FFFFFFFUL)
// goto Lno;
else if ((int)value != value)
goto Lno;
goto Lyes;
@@ -439,9 +452,12 @@ MATCH StructLiteralExp::implicitConvTo(Type *t)
{
m = MATCHconst;
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (*elements)[i];
{
Expression *e = (*elements)[i];
if (!e)
continue;
Type *te = e->type;
te = te->castMod(t->mod);
te = sd->fields[i]->type->addMod(t->mod);
MATCH m2 = e->implicitConvTo(te);
//printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2);
if (m2 < m)
@@ -638,9 +654,36 @@ MATCH CallExp::implicitConvTo(Type *t)
/* Allow the result of strongly pure functions to
* convert to immutable
*/
if (f && f->isPure() == PUREstrong && !f->type->hasWild())
if (f && f->isolateReturn())
return type->invariantOf()->implicitConvTo(t);
/* The result of arr.dup and arr.idup can be unique essentially.
* So deal with this case specially.
*/
if (!f && e1->op == TOKvar && ((VarExp *)e1)->var->ident == Id::adDup &&
t->toBasetype()->ty == Tarray)
{
assert(type->toBasetype()->ty == Tarray);
assert(arguments->dim == 2);
Expression *eorg = (*arguments)[1];
Type *tn = t->nextOf();
if (type->nextOf()->implicitConvTo(tn) < MATCHconst)
{
/* If the operand is an unique array literal, then allow conversion.
*/
if (eorg->op != TOKarrayliteral)
return MATCHnomatch;
Expressions *elements = ((ArrayLiteralExp *)eorg)->elements;
for (size_t i = 0; i < elements->dim; i++)
{
if (!(*elements)[i]->implicitConvTo(tn))
return MATCHnomatch;
}
}
m = type->invariantOf()->implicitConvTo(t);
return m;
}
return MATCHnomatch;
}
@@ -969,6 +1012,39 @@ MATCH NewExp::implicitConvTo(Type *t)
return MATCHnomatch;
}
Type *SliceExp::toStaticArrayType()
{
if (lwr && upr)
{
Expression *lwr = this->lwr->optimize(WANTvalue);
Expression *upr = this->upr->optimize(WANTvalue);
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 NULL;
}
MATCH SliceExp::implicitConvTo(Type *t)
{
MATCH result = Expression::implicitConvTo(t);
Type *tb = t->toBasetype();
Type *typeb = type->toBasetype();
if (result == MATCHnomatch &&
tb->ty == Tsarray && typeb->ty == Tarray &&
lwr && upr)
{
typeb = toStaticArrayType();
if (typeb)
result = typeb->implicitConvTo(t);
}
return result;
}
/* ==================== castTo ====================== */
/**************************************
@@ -984,6 +1060,15 @@ Expression *Expression::castTo(Scope *sc, Type *t)
#endif
if (type == t)
return this;
if (op == TOKvar)
{
VarDeclaration *v = ((VarExp *)this)->var->isVarDeclaration();
if (v && v->storage_class & STCmanifest)
{
Expression *e = optimize(WANTvalue | WANTinterpret);
return e->castTo(sc, t);
}
}
Expression *e = this;
Type *tb = t->toBasetype();
Type *typeb = type->toBasetype();
@@ -1162,6 +1247,14 @@ Expression *NullExp::castTo(Scope *sc, Type *t)
return e;
}
Expression *StructLiteralExp::castTo(Scope *sc, Type *t)
{
Expression *e = Expression::castTo(sc, t);
if (e->op == TOKstructliteral)
((StructLiteralExp *)e)->stype = t; // commit type
return e;
}
Expression *StringExp::castTo(Scope *sc, Type *t)
{
/* This follows copy-on-write; any changes to 'this'
@@ -1465,7 +1558,9 @@ Expression *AddrExp::castTo(Scope *sc, Type *t)
Expression *TupleExp::castTo(Scope *sc, Type *t)
{ TupleExp *e = (TupleExp *)copy();
{
TupleExp *e = (TupleExp *)copy();
e->e0 = e0 ? e0->copy() : NULL;
e->exps = (Expressions *)exps->copy();
for (size_t i = 0; i < e->exps->dim; i++)
{ Expression *ex = (*e->exps)[i];
@@ -1490,7 +1585,9 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
if ((tb->ty == Tarray || tb->ty == Tsarray) &&
(typeb->ty == Tarray || typeb->ty == Tsarray) &&
// Not trying to convert non-void[] to void[]
!(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid))
!(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid) &&
// Not trying to convert void[n] to others
!(typeb->ty == Tsarray && typeb->nextOf()->toBasetype()->ty == Tvoid))
{
if (tb->ty == Tsarray)
{ TypeSArray *tsa = (TypeSArray *)tb;
@@ -1699,7 +1796,8 @@ Expression *FuncExp::castTo(Scope *sc, Type *t)
e = e->castTo(sc, t);
else if (!e->type->equals(t))
{
assert(e->type->nextOf()->covariant(t->nextOf()) == 1);
assert(t->ty == Tpointer && t->nextOf()->ty == Tvoid || // Bugzilla 9928
e->type->nextOf()->covariant(t->nextOf()) == 1);
e = e->copy();
e->type = t;
}
@@ -1741,19 +1839,42 @@ Expression *CommaExp::castTo(Scope *sc, Type *t)
return e;
}
Expression *SliceExp::castTo(Scope *sc, Type *t)
{
Type *typeb = type->toBasetype();
Type *tb = t->toBasetype();
Expression *e;
if (typeb->ty == Tarray && tb->ty == Tsarray)
{
/* If a SliceExp has Tsarray, it will become lvalue.
* That's handled in SliceExp::isLvalue and toLvalue
*/
e = copy();
e->type = t;
}
else
{
e = Expression::castTo(sc, t);
}
return e;
}
/* ==================== inferType ====================== */
/****************************************
* Set type inference target
* t Target type
* flag 1: don't put an error when inference fails
* sc it is used for the semantic of t, when != NULL
* tparams template parameters should be inferred
*/
Expression *Expression::inferType(Type *t, int flag, TemplateParameters *tparams)
Expression *Expression::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
return this;
}
Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams)
Expression *ArrayLiteralExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
if (t)
{
@@ -1764,7 +1885,7 @@ Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tp
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (*elements)[i];
if (e)
{ e = e->inferType(tn, flag, tparams);
{ e = e->inferType(tn, flag, sc, tparams);
(*elements)[i] = e;
}
}
@@ -1773,7 +1894,7 @@ Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tp
return this;
}
Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams)
Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
if (t)
{
@@ -1785,14 +1906,14 @@ Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameter
for (size_t i = 0; i < keys->dim; i++)
{ Expression *e = (*keys)[i];
if (e)
{ e = e->inferType(ti, flag, tparams);
{ e = e->inferType(ti, flag, sc, tparams);
(*keys)[i] = e;
}
}
for (size_t i = 0; i < values->dim; i++)
{ Expression *e = (*values)[i];
if (e)
{ e = e->inferType(tv, flag, tparams);
{ e = e->inferType(tv, flag, sc, tparams);
(*values)[i] = e;
}
}
@@ -1801,7 +1922,7 @@ Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameter
return this;
}
Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters *tparams)
{
if (!to)
return this;
@@ -1859,7 +1980,10 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
Type *tprm = p->type;
if (tprm->reliesOnTident(tparams))
goto L1;
tprm = tprm->semantic(loc, td->scope);
if (sc)
tprm = tprm->semantic(loc, sc);
if (tprm->ty == Terror)
goto L1;
tiargs->push(tprm);
u = dim; // break inner loop
}
@@ -1915,13 +2039,13 @@ L1:
return e;
}
Expression *CondExp::inferType(Type *t, int flag, TemplateParameters *tparams)
Expression *CondExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams)
{
if (t)
{
t = t->toBasetype();
e1 = e1->inferType(t, flag, tparams);
e2 = e2->inferType(t, flag, tparams);
e1 = e1->inferType(t, flag, sc, tparams);
e2 = e2->inferType(t, flag, sc, tparams);
}
return this;
}
@@ -1947,8 +2071,8 @@ Expression *BinExp::scaleFactor(Scope *sc)
stride = t1b->nextOf()->size(loc);
if (!t->equals(t2b))
e2 = e2->castTo(sc, t);
e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t));
eoff = e2;
e2 = new MulExp(loc, e2, new IntegerExp(Loc(), stride, t));
e2->type = t;
type = e1->type;
}
@@ -1963,8 +2087,8 @@ Expression *BinExp::scaleFactor(Scope *sc)
e = e1->castTo(sc, t);
else
e = e1;
e = new MulExp(loc, e, new IntegerExp(0, stride, t));
eoff = e;
e = new MulExp(loc, e, new IntegerExp(Loc(), stride, t));
e->type = t;
type = e2->type;
e1 = e2;
@@ -2049,6 +2173,14 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
assert(t1);
Type *t = t1;
/* The start type of alias this type recursion.
* In following case, we should save A, and stop recursion
* if it appears again.
* X -> Y -> [A] -> B -> A -> B -> ...
*/
Type *att1 = NULL;
Type *att2 = NULL;
//if (t1) printf("\tt1 = %s\n", t1->toChars());
//if (t2) printf("\tt2 = %s\n", t2->toChars());
#ifdef DEBUG
@@ -2356,12 +2488,22 @@ Lcc:
}
else if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
{
if (att1 && e1->type == att1)
goto Lincompatible;
if (!att1 && e1->type->checkAliasThisRec())
att1 = e1->type;
//printf("att tmerge(c || c) e1 = %s\n", e1->type->toChars());
e1 = resolveAliasThis(sc, e1);
t1 = e1->type;
continue;
}
else if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
{
if (att2 && e2->type == att2)
goto Lincompatible;
if (!att2 && e2->type->checkAliasThisRec())
att2 = e2->type;
//printf("att tmerge(c || c) e2 = %s\n", e2->type->toChars());
e2 = resolveAliasThis(sc, e2);
t2 = e2->type;
continue;
@@ -2397,11 +2539,21 @@ Lcc:
Expression *e2b = NULL;
if (ts2->sym->aliasthis)
{
if (att2 && e2->type == att2)
goto Lincompatible;
if (!att2 && e2->type->checkAliasThisRec())
att2 = e2->type;
//printf("att tmerge(s && s) e2 = %s\n", e2->type->toChars());
e2b = resolveAliasThis(sc, e2);
i1 = e2b->implicitConvTo(t1);
}
if (ts1->sym->aliasthis)
{
if (att1 && e1->type == att1)
goto Lincompatible;
if (!att1 && e1->type->checkAliasThisRec())
att1 = e1->type;
//printf("att tmerge(s && s) e1 = %s\n", e1->type->toChars());
e1b = resolveAliasThis(sc, e1);
i2 = e1b->implicitConvTo(t2);
}
@@ -2429,6 +2581,11 @@ Lcc:
{
if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
{
if (att1 && e1->type == att1)
goto Lincompatible;
if (!att1 && e1->type->checkAliasThisRec())
att1 = e1->type;
//printf("att tmerge(s || s) e1 = %s\n", e1->type->toChars());
e1 = resolveAliasThis(sc, e1);
t1 = e1->type;
t = t1;
@@ -2436,6 +2593,11 @@ Lcc:
}
if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
{
if (att2 && e2->type == att2)
goto Lincompatible;
if (!att2 && e2->type->checkAliasThisRec())
att2 = e2->type;
//printf("att tmerge(s || s) e2 = %s\n", e2->type->toChars());
e2 = resolveAliasThis(sc, e2);
t2 = e2->type;
t = t2;
@@ -2472,6 +2634,7 @@ Lcc:
{
e2 = e2->castTo(sc, t1);
t2 = t1;
t = t1;
goto Lagain;
}
else if (t2->ty == Tvector && t1->ty != Tvector &&
@@ -2479,6 +2642,7 @@ Lcc:
{
e1 = e1->castTo(sc, t2);
t1 = t2;
t = t1;
goto Lagain;
}
else if (t1->isintegral() && t2->isintegral())
@@ -2576,6 +2740,11 @@ Expression *BinExp::typeCombine(Scope *sc)
if (!typeMerge(sc, this, &type, &e1, &e2))
goto Lerror;
// If the types have no value, return an error
if (e1->op == TOKerror)
return e1;
if (e2->op == TOKerror)
return e2;
return this;
Lerror:
@@ -2615,6 +2784,8 @@ Expression *Expression::integralPromotions(Scope *sc)
case Tdchar:
e = e->castTo(sc, Type::tuns32);
break;
default:
break;
}
return e;
}
+103 -91
View File
@@ -15,6 +15,7 @@
#include "root.h"
#include "rmem.h"
#include "target.h"
#include "enum.h"
#include "init.h"
@@ -220,11 +221,16 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
}
#if !MODULEINFO_IS_STRUCT
#ifdef DMDV2
if (id == Id::ModuleInfo && !Module::moduleinfo)
Module::moduleinfo = this;
#else
if (id == Id::ModuleInfo)
{ if (Module::moduleinfo)
Module::moduleinfo->error("%s", msg);
Module::moduleinfo = this;
}
#endif
#endif
}
@@ -232,6 +238,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla
isscope = 0;
isabstract = 0;
inuse = 0;
doAncestorsSemantic = SemanticStart;
}
Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
@@ -280,7 +287,7 @@ void ClassDeclaration::semantic(Scope *sc)
type = type->semantic(loc, sc);
handle = type;
if (!members) // if forward reference
if (!members) // if opaque declaration
{ //printf("\tclass '%s' is forward referenced\n", toChars());
return;
}
@@ -300,7 +307,7 @@ void ClassDeclaration::semantic(Scope *sc)
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
int errors = global.gaggedErrors;
int errors = global.errors;
if (sc->stc & STCdeprecated)
{
@@ -376,7 +383,7 @@ void ClassDeclaration::semantic(Scope *sc)
}
if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
{ // Try to resolve forward reference
if (/*sc->mustsemantic &&*/ tc->sym->scope)
if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope)
tc->sym->semantic(NULL);
}
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
@@ -444,7 +451,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (!tc->sym->symtab)
{ // Try to resolve forward reference
if (/*sc->mustsemantic &&*/ tc->sym->scope)
if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope)
tc->sym->semantic(NULL);
}
@@ -464,6 +471,8 @@ void ClassDeclaration::semantic(Scope *sc)
}
i++;
}
if (doAncestorsSemantic == SemanticIn)
doAncestorsSemantic = SemanticDone;
// If no base class, and this is not an Object, use Object as base class
@@ -508,6 +517,7 @@ void ClassDeclaration::semantic(Scope *sc)
com = baseClass->isCOMclass();
isscope = baseClass->isscope;
vthis = baseClass->vthis;
enclosing = baseClass->enclosing;
storage_class |= baseClass->storage_class & STC_TYPECTOR;
}
else
@@ -535,7 +545,6 @@ void ClassDeclaration::semantic(Scope *sc)
*/
if (vthis) // if inheriting from nested class
{ // Use the base class's 'this' member
isnested = true;
if (storage_class & STCstatic)
error("static class cannot inherit from nested class %s", baseClass->toChars());
if (toParent2() != baseClass->toParent2() &&
@@ -556,41 +565,11 @@ void ClassDeclaration::semantic(Scope *sc)
baseClass->toChars(),
baseClass->toParent2()->toChars());
}
isnested = false;
}
}
else if (!(storage_class & STCstatic))
{ Dsymbol *s = toParent2();
if (s)
{
AggregateDeclaration *ad = s->isClassDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
if (ad || fd)
{ isnested = true;
Type *t;
if (ad)
t = ad->handle;
else if (fd)
{ AggregateDeclaration *ad2 = fd->isMember2();
if (ad2)
t = ad2->handle;
else
{
t = Type::tvoidptr;
}
}
else
assert(0);
if (t->ty == Tstruct) // ref to struct
t = Type::tvoidptr;
assert(!vthis);
vthis = new ThisDeclaration(loc, t);
members->push(vthis);
}
enclosing = NULL;
}
}
else
makeNested();
}
if (storage_class & STCauto)
@@ -627,12 +606,12 @@ void ClassDeclaration::semantic(Scope *sc)
if (baseClass)
{ sc->offset = baseClass->structsize;
alignsize = baseClass->alignsize;
// if (isnested)
// sc->offset += PTRSIZE; // room for uplevel context pointer
// if (enclosing)
// sc->offset += Target::ptrsize; // room for uplevel context pointer
}
else
{ sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor
alignsize = PTRSIZE;
{ sc->offset = Target::ptrsize * 2; // allow room for __vptr and __monitor
alignsize = Target::ptrsize;
}
sc->userAttributes = NULL;
structsize = sc->offset;
@@ -674,8 +653,8 @@ void ClassDeclaration::semantic(Scope *sc)
}
sc->offset = structsize;
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
if (global.errors != errors)
{ // The type is no good.
type = Type::terror;
}
@@ -713,43 +692,57 @@ void ClassDeclaration::semantic(Scope *sc)
/* Look for special member functions.
* They must be in this class, not in a base class.
*/
ctor = search(0, Id::ctor, 0);
ctor = search(Loc(), Id::ctor, 0);
#if DMDV1
if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
ctor = NULL;
#else
if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration())))
ctor = NULL; // search() looks through ancestor classes
if (!ctor && noDefaultCtor)
{
// A class object is always created by constructor, so this check is legitimate.
for (size_t i = 0; i < fields.dim; i++)
{
VarDeclaration *v = fields[i]->isVarDeclaration();
if (v->storage_class & STCnodefaultctor)
::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 = (InvariantDeclaration *)search(Id::classInvariant, 0);
// if (inv && inv->toParent() != this)
// inv = NULL;
inv = buildInv(sc);
// Can be in base class
aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
aggNew = (NewDeclaration *)search(Loc(), Id::classNew, 0);
aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete, 0);
// If this class has no constructor, but base class does, create
// a constructor:
// If this class has no constructor, but base class has a default
// ctor, create a constructor:
// this() { }
if (!ctor && baseClass && baseClass->ctor)
{
//printf("Creating default this(){} for class %s\n", toChars());
Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0);
CtorDeclaration *ctor = new CtorDeclaration(loc, 0, 0, tf);
ctor->isImplicit = true;
ctor->fbody = new CompoundStatement(0, new Statements());
members->push(ctor);
ctor->addMember(sc, this, 1);
*sc = scsave; // why? What about sc->nofree?
ctor->semantic(sc);
this->ctor = ctor;
defaultCtor = ctor;
if (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);
CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf);
ctor->fbody = new CompoundStatement(Loc(), new Statements());
members->push(ctor);
ctor->addMember(sc, this, 1);
*sc = scsave; // why? What about sc->nofree?
ctor->semantic(sc);
this->ctor = ctor;
defaultCtor = ctor;
}
else
{
error("Cannot implicitly generate a default ctor when base class %s is missing a default ctor", baseClass->toPrettyChars());
}
}
#if 0
@@ -766,7 +759,7 @@ void ClassDeclaration::semantic(Scope *sc)
for (size_t i = 0; i < vtblInterfaces->dim; i++)
{
BaseClass *b = (*vtblInterfaces)[i];
unsigned thissize = PTRSIZE;
unsigned thissize = Target::ptrsize;
alignmember(STRUCTALIGN_DEFAULT, thissize, &sc->offset);
assert(b->offset == 0);
@@ -795,13 +788,10 @@ void ClassDeclaration::semantic(Scope *sc)
Module::dprogress++;
dtor = buildDtor(sc);
if (Dsymbol *assign = search_function(this, Id::assign))
if (FuncDeclaration *f = hasIdentityOpAssign(sc))
{
if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign))
{
if (!(f->storage_class & STCdisable))
error("identity assignment operator overload is illegal");
}
if (!(f->storage_class & STCdisable))
error("identity assignment operator overload is illegal");
}
sc->pop();
@@ -821,6 +811,15 @@ void ClassDeclaration::semantic(Scope *sc)
deferred->semantic2(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);
}
#endif
assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
}
void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -837,7 +836,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
BaseClass *b = (*baseclasses)[i];
if (i)
buf->writeByte(',');
buf->writestring(", ");
//buf->writestring(b->base->ident->toChars());
b->type->toCBuffer(buf, NULL, hgs);
}
@@ -941,19 +940,24 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
Dsymbol *s;
//printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
if (scope && !symtab)
{ Scope *sc = scope;
sc->mustsemantic++;
//if (scope) printf("%s doAncestorsSemantic = %d\n", toChars(), doAncestorsSemantic);
if (scope && doAncestorsSemantic == SemanticStart)
{
// must semantic on base class/interfaces
doAncestorsSemantic = SemanticIn;
// If speculatively gagged, ungag now.
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging())
global.gag = 0;
semantic(sc);
semantic(scope);
global.gag = oldgag;
sc->mustsemantic--;
if (doAncestorsSemantic != SemanticDone)
doAncestorsSemantic = SemanticStart;
}
if (!members || !symtab)
if (!members || !symtab) // opaque or semantic() is not yet called
{
error("is forward referenced when looking for '%s'", ident->toChars());
//*(char*)0=0;
@@ -987,17 +991,17 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
return s;
}
Dsymbol *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
ClassDeclaration *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
{
// Search bases classes in depth-first, left to right order
for (size_t i = 0; i < baseclasses->dim; i++)
{
BaseClass *b = (*baseclasses)[i];
Dsymbol *cdb = b->type->isClassHandle();
ClassDeclaration *cdb = b->type->isClassHandle();
if (cdb->ident->equals(ident))
return cdb;
cdb = ((ClassDeclaration *)cdb)->searchBase(loc, ident);
cdb = cdb->searchBase(loc, ident);
if (cdb)
return cdb;
}
@@ -1019,7 +1023,7 @@ int isf(void *param, FuncDeclaration *fd)
int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
{
//printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
Dsymbol *s = search(0, fd->ident, 4|2);
Dsymbol *s = search(Loc(), fd->ident, 4|2);
if (!s)
{ //printf("not found\n");
/* Because, due to a hack, if there are multiple definitions
@@ -1289,7 +1293,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
scope = NULL;
}
int errors = global.gaggedErrors;
int errors = global.errors;
if (sc->stc & STCdeprecated)
{
@@ -1359,7 +1363,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
}
if (!b->base->symtab)
{ // Try to resolve forward reference
if (sc->mustsemantic && b->base->scope)
if (doAncestorsSemantic == SemanticIn && b->base->scope)
b->base->semantic(NULL);
}
if (!b->base->symtab || b->base->scope || b->base->inuse)
@@ -1379,6 +1383,8 @@ void InterfaceDeclaration::semantic(Scope *sc)
#endif
i++;
}
if (doAncestorsSemantic == SemanticIn)
doAncestorsSemantic = SemanticDone;
interfaces_dim = baseclasses->dim;
interfaces = baseclasses->tdata();
@@ -1438,7 +1444,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
sc->protection = PROTpublic;
sc->explicitProtection = 0;
// structalign = sc->structalign;
sc->offset = PTRSIZE * 2;
sc->offset = Target::ptrsize * 2;
sc->userAttributes = NULL;
structsize = sc->offset;
inuse++;
@@ -1464,8 +1470,8 @@ void InterfaceDeclaration::semantic(Scope *sc)
s->semantic(sc);
}
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
if (global.errors != errors)
{ // The type is no good.
type = Type::terror;
}
@@ -1473,6 +1479,15 @@ void InterfaceDeclaration::semantic(Scope *sc)
//members->print();
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);
}
#endif
assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
}
@@ -1664,8 +1679,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins
if (newinstance &&
fd->toParent() != cd &&
ifd->toParent() == base)
cd->error("interface function %s.%s is not implemented",
id->toChars(), ifd->ident->toChars());
cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
if (fd->toParent() == cd)
result = 1;
@@ -1675,9 +1689,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins
//printf(" not found\n");
// BUG: should mark this class as abstract?
if (!cd->isAbstract())
cd->error("interface function %s.%s%s isn't implemented",
id->toChars(), ifd->ident->toChars(),
Parameter::argsTypesToChars(tf->parameters, tf->varargs));
cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
fd = NULL;
}
+346 -253
View File
@@ -24,44 +24,72 @@
#include "template.h"
/*******************************************
* Merge function attributes pure, nothrow, @safe, and @disable
*/
StorageClass mergeFuncAttrs(StorageClass s1, StorageClass s2)
{
StorageClass stc = 0;
StorageClass sa = s1 & s2;
StorageClass so = s1 | s2;
if (so & STCsystem)
stc |= STCsystem;
else if (sa & STCtrusted)
stc |= STCtrusted;
else if ((so & (STCtrusted | STCsafe)) == (STCtrusted | STCsafe))
stc |= STCtrusted;
else if (sa & STCsafe)
stc |= STCsafe;
if (sa & STCpure)
stc |= STCpure;
if (sa & STCnothrow)
stc |= STCnothrow;
if (so & STCdisable)
stc |= STCdisable;
return stc;
}
/*******************************************
* Check given opAssign symbol is really identity opAssign or not.
*/
FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc, Dsymbol *assign)
FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc)
{
Dsymbol *assign = search_function(this, Id::assign);
if (assign)
{
assert(assign->ident == Id::assign);
/* check identity opAssign exists
*/
Expression *er = new NullExp(loc, type); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
el->type = type;
Expressions ar; ar.push(er);
Expressions al; al.push(el);
Expressions *a = new Expressions();
a->setDim(1);
FuncDeclaration *f = NULL;
if (FuncDeclaration *fd = assign->isFuncDeclaration())
{
f = fd->overloadResolve(loc, er, &ar, 1);
if (!f) f = fd->overloadResolve(loc, er, &al, 1);
}
if (TemplateDeclaration *td = assign->isTemplateDeclaration())
{
unsigned errors = global.startGagging(); // Do not report errors, even if the
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
Scope *sc2 = sc->push();
sc2->speculative = true;
f = td->deduceFunctionTemplate(sc2, loc, NULL, er, &ar, 1);
if (!f) f = td->deduceFunctionTemplate(sc2, loc, NULL, er, &al, 1);
unsigned errors = global.startGagging(); // Do not report errors, even if the
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
sc = sc->push();
sc->speculative = true;
sc2->pop();
global.speculativeGag = oldspec;
global.endGagging(errors);
for (size_t i = 0; i < 2; i++)
{
(*a)[0] = (i == 0 ? er : el);
f = resolveFuncCall(loc, sc, assign, NULL, type, a, 1);
if (f)
break;
}
sc = sc->pop();
global.speculativeGag = oldspec;
global.endGagging(errors);
if (f)
{
int varargs;
@@ -104,7 +132,7 @@ int StructDeclaration::needOpAssign()
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
assert(v && v->isField());
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
@@ -133,41 +161,53 @@ Lneed:
* Build opAssign for struct.
* ref S opAssign(S s) { ... }
*
* Note that s will be constructed onto the stack, probably copy-constructed.
* Then, the body is:
* S tmp = this; // bit copy
* this = s; // bit copy
* tmp.dtor();
* 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,
* the body will make bit-wise object swap:
* S __tmp = this; // bit copy
* this = s; // bit copy
* __tmp.dtor();
* Instead of running the destructor on s, run it on tmp instead.
*
* Otherwise, the body will make member-wise assignments:
* Then, the body is:
* this.field1 = s.field1;
* this.field2 = s.field2;
* ...;
*/
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
{
Dsymbol *assign = search_function(this, Id::assign);
if (assign)
if (FuncDeclaration *f = hasIdentityOpAssign(sc))
{
if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign))
return f;
// Even if non-identity opAssign is defined, built-in identity opAssign
// will be defined. (Is this an exception of operator overloading rule?)
hasIdentityAssign = 1;
return f;
}
// Even if non-identity opAssign is defined, built-in identity opAssign
// will be defined.
if (!needOpAssign())
return NULL;
//printf("StructDeclaration::buildOpAssign() %s\n", toChars());
StorageClass stc = STCundefined;
Loc declLoc = this->loc;
Loc loc = Loc(); // internal code should have no loc to prevent coverage
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;
FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype);
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, ftype);
Expression *e = NULL;
if (postblit)
{ /* Swap:
* tmp = *this; *this = s; tmp.dtor();
if (dtor || postblit)
{
/* Do swap this and rhs
* tmp = this; this = s; tmp.dtor();
*/
//printf("\tswap copy\n");
Identifier *idtmp = Lexer::uniqueId("__tmp");
@@ -175,20 +215,20 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
AssignExp *ec = NULL;
if (dtor)
{
tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
tmp = new VarDeclaration(loc, type, idtmp, new VoidInitializer(loc));
tmp->noscope = 1;
tmp->storage_class |= STCctfe;
e = new DeclarationExp(0, tmp);
ec = new AssignExp(0,
new VarExp(0, tmp),
new ThisExp(0)
e = new DeclarationExp(loc, tmp);
ec = new AssignExp(loc,
new VarExp(loc, tmp),
new ThisExp(loc)
);
ec->op = TOKblit;
e = Expression::combine(e, ec);
}
ec = new AssignExp(0,
new ThisExp(0),
new IdentifierExp(0, Id::p));
ec = new AssignExp(loc,
new ThisExp(loc),
new IdentifierExp(loc, Id::p));
ec->op = TOKblit;
e = Expression::combine(e, ec);
if (dtor)
@@ -196,38 +236,41 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
/* Instead of running the destructor on s, run it
* on tmp. This avoids needing to copy tmp back in to s.
*/
Expression *ec2 = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
ec2 = new CallExp(0, ec2);
Expression *ec2 = new DotVarExp(loc, new VarExp(loc, tmp), dtor, 0);
ec2 = new CallExp(loc, ec2);
e = Expression::combine(e, ec2);
}
}
else
{ /* Do memberwise copy
{
/* Do memberwise copy
*/
//printf("\tmemberwise copy\n");
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
assert(v && v->isField());
// this.v = s.v;
AssignExp *ec = new AssignExp(0,
new DotVarExp(0, new ThisExp(0), v, 0),
new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
AssignExp *ec = new AssignExp(loc,
new DotVarExp(loc, new ThisExp(loc), v, 0),
new DotVarExp(loc, new IdentifierExp(loc, Id::p), v, 0));
e = Expression::combine(e, ec);
}
}
Statement *s1 = new ExpStatement(0, e);
Statement *s1 = new ExpStatement(loc, e);
/* Add:
* return this;
*/
e = new ThisExp(0);
Statement *s2 = new ReturnStatement(0, e);
e = new ThisExp(loc);
Statement *s2 = new ReturnStatement(loc, e);
fop->fbody = new CompoundStatement(0, s1, s2);
fop->fbody = new CompoundStatement(loc, s1, s2);
Dsymbol *s = fop;
#if 1 // workaround until fixing issue 1528
Dsymbol *assign = search_function(this, Id::assign);
if (assign && assign->isTemplateDeclaration())
{
// Wrap a template around the function declaration
@@ -238,6 +281,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0);
s = tempdecl;
}
#endif
members->push(s);
s->addMember(sc, this, 1);
this->hasIdentityAssign = 1; // temporary mark identity assignable
@@ -281,10 +325,8 @@ int StructDeclaration::needOpEquals()
if (hasIdentityEquals)
goto Lneed;
#if 0
if (isUnionDeclaration())
goto Ldontneed;
#endif
/* If any of the fields has an opEquals, then we
* need it too.
@@ -293,18 +335,18 @@ int StructDeclaration::needOpEquals()
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
assert(v && v->isField());
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
#if 0
if (tv->isfloating())
goto Lneed;
if (tv->ty == Tarray)
goto Lneed;
if (tv->ty == Taarray)
goto Lneed;
if (tv->ty == Tclass)
goto Lneed;
#endif
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
@@ -326,128 +368,107 @@ Lneed:
#undef X
}
/******************************************
* Build opEquals for struct.
* const bool opEquals(const S s) { ... }
*/
FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
{
Dsymbol *eq = search_function(this, Id::eq);
if (eq)
{
for (size_t i = 0; i <= 1; i++)
/* check identity opEquals exists
*/
Expression *er = new NullExp(loc, NULL); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
Expressions *a = new Expressions();
a->setDim(1);
for (size_t i = 0; ; i++)
{
Expression *e =
i == 0 ? new NullExp(loc, type->constOf()) // dummy rvalue
: type->constOf()->defaultInit(); // dummy lvalue
Expressions *arguments = new Expressions();
arguments->push(e);
Type *tthis;
if (i == 0) tthis = type;
if (i == 1) tthis = type->constOf();
if (i == 2) tthis = type->invariantOf();
if (i == 3) tthis = type->sharedOf();
if (i == 4) tthis = type->sharedConstOf();
if (i == 5) break;
FuncDeclaration *f = NULL;
// check identity opEquals exists
FuncDeclaration *fd = eq->isFuncDeclaration();
if (fd)
{ fd = fd->overloadResolve(loc, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
return fd;
unsigned errors = global.startGagging(); // Do not report errors, even if the
unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it.
global.speculativeGag = global.gag;
sc = sc->push();
sc->speculative = true;
for (size_t j = 0; j < 2; j++)
{
(*a)[0] = (j == 0 ? er : el);
(*a)[0]->type = tthis;
f = resolveFuncCall(loc, sc, eq, NULL, tthis, a, 1);
if (f)
break;
}
TemplateDeclaration *td = eq->isTemplateDeclaration();
if (td)
{ fd = td->deduceFunctionTemplate(sc, loc, NULL, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
return fd;
}
sc = sc->pop();
global.speculativeGag = oldspec;
global.endGagging(errors);
if (f)
return f;
}
return NULL;
}
return NULL;
}
if (!needOpEquals())
return NULL;
/******************************************
* Build opEquals for struct.
* const bool opEquals(const S s) { ... }
*
* By fixing bugzilla 3789, opEquals is changed to be never implicitly generated.
* Now, struct objects comparison s1 == s2 is translated to:
* s1.tupleof == s2.tupleof
* to calculate structural equality. See EqualExp::semantic.
*/
//printf("StructDeclaration::buildOpEquals() %s\n", toChars());
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCin, type, Id::p, NULL));
TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tf->mod = MODconst;
tf = (TypeFunction *)tf->semantic(loc, sc);
FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::eq, STCundefined, tf);
Expression *e = NULL;
/* Do memberwise compare
*/
//printf("\tmemberwise compare\n");
for (size_t i = 0; i < fields.dim; i++)
FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
{
if (FuncDeclaration *f = hasIdentityOpEquals(sc))
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
assert(0); // what should we do with this?
// this.v == s.v;
EqualExp *ec = new EqualExp(TOKequal, loc,
new DotVarExp(loc, new ThisExp(loc), v, 0),
new DotVarExp(loc, new IdentifierExp(loc, Id::p), v, 0));
if (e)
e = new AndAndExp(loc, e, ec);
else
e = ec;
hasIdentityEquals = 1;
}
if (!e)
e = new IntegerExp(loc, 1, Type::tbool);
fop->fbody = new ReturnStatement(loc, e);
members->push(fop);
fop->addMember(sc, this, 1);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fop->semantic(sc);
sc->pop();
//printf("-StructDeclaration::buildOpEquals() %s\n", toChars());
return fop;
return NULL;
}
/******************************************
* Build __xopEquals for TypeInfo_Struct
* bool __xopEquals(in void* p, in void* q) { ... }
* static bool __xopEquals(ref const S p, ref const S q)
* {
* return p == q;
* }
*
* This is called by TypeInfo.equals(p1, p2). If the struct does not support
* const objects comparison, it will throw "not implemented" Error in runtime.
*/
FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
{
if (!search_function(this, Id::eq))
if (!needOpEquals())
return NULL;
/* static bool__xopEquals(in void* p, in void* q) {
* return ( *cast(const S*)(p) ).opEquals( *cast(const S*)(q) );
* }
*/
//printf("StructDeclaration::buildXopEquals() %s\n", toChars());
Loc declLoc = Loc(); // loc is unnecessary so __xopEquals is never called directly
Loc loc = Loc(); // loc is unnecessary so errors are gagged
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::p, NULL));
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::q, NULL));
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::tbool, 0, LINKd);
tf = (TypeFunction *)tf->semantic(0, sc);
tf = (TypeFunction *)tf->semantic(loc, sc);
Identifier *id = Lexer::idPool("__xopEquals");
FuncDeclaration *fop = new FuncDeclaration(0, 0, id, STCstatic, tf);
FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), id, STCstatic, tf);
Expression *e = new CallExp(0,
new DotIdExp(0,
new PtrExp(0, new CastExp(0,
new IdentifierExp(0, Id::p), type->pointerTo()->constOf())),
Id::eq),
new PtrExp(0, new CastExp(0,
new IdentifierExp(0, Id::q), type->pointerTo()->constOf())));
Expression *e1 = new IdentifierExp(loc, Id::p);
Expression *e2 = new IdentifierExp(loc, Id::q);
Expression *e = new EqualExp(TOKequal, loc, e1, e2);
fop->fbody = new ReturnStatement(0, e);
fop->fbody = new ReturnStatement(loc, e);
size_t index = members->dim;
members->push(fop);
@@ -472,9 +493,9 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
if (!xerreq)
{
Expression *e = new IdentifierExp(0, Id::empty);
e = new DotIdExp(0, e, Id::object);
e = new DotIdExp(0, e, Lexer::idPool("_xopEquals"));
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();
@@ -489,17 +510,17 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
return fop;
}
/*******************************************
* Build copy constructor for struct.
* void __cpctpr(ref const S s) const [pure nothrow @trusted]
* {
* (*cast(S*)&this) = *cast(S*)s;
* (*cast(S*)&this).postBlit();
* }
*
* Copy constructors are compiler generated only, and are only
* callable from the compiler. They are not user accessible.
* A copy constructor is:
* void cpctpr(ref const S s) const
* {
* (*cast(S*)&this) = *cast(S*)s;
* (*cast(S*)&this).postBlit();
* }
*
* This is done so:
* - postBlit() never sees uninitialized data
* - memcpy can be much more efficient than memberwise copy
@@ -508,62 +529,59 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
{
//printf("StructDeclaration::buildCpCtor() %s\n", toChars());
FuncDeclaration *fcp = NULL;
/* Copy constructor is only necessary if there is a postblit function,
* otherwise the code generator will just do a bit copy.
*/
if (postblit)
if (!postblit)
return NULL;
//printf("StructDeclaration::buildCpCtor() %s\n", toChars());
StorageClass stc = STCsafe | STCnothrow | STCpure;
Loc declLoc = postblit->loc;
Loc loc = Loc(); // internal code should have no loc to prevent coverage
stc = mergeFuncAttrs(stc, postblit->storage_class);
if (stc & STCsafe) // change to @trusted for unsafe casts
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;
FuncDeclaration *fcp = new FuncDeclaration(declLoc, Loc(), Id::cpctor, stc, ftype);
if (!(stc & STCdisable))
{
//printf("generating cpctor\n");
// Build *this = p;
Expression *e = new ThisExp(loc);
AssignExp *ea = new AssignExp(loc,
new PtrExp(loc, new CastExp(loc, new AddrExp(loc, e), type->mutableOf()->pointerTo())),
new PtrExp(loc, new CastExp(loc, new AddrExp(loc, new IdentifierExp(loc, Id::p)), type->mutableOf()->pointerTo()))
);
ea->op = TOKblit;
Statement *s = new ExpStatement(loc, ea);
StorageClass stc = postblit->storage_class &
(STCdisable | STCsafe | STCtrusted | STCsystem | STCpure | STCnothrow);
if (stc & (STCsafe | STCtrusted))
stc = stc & ~STCsafe | STCtrusted;
// Build postBlit();
e = new ThisExp(loc);
e = new PtrExp(loc, new CastExp(loc, new AddrExp(loc, e), type->mutableOf()->pointerTo()));
e = new DotVarExp(loc, e, postblit, 0);
e = new CallExp(loc, e);
Parameters *fparams = new Parameters;
fparams->push(new Parameter(STCref, type->constOf(), Id::p, NULL));
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd, stc);
ftype->mod = MODconst;
fcp = new FuncDeclaration(loc, 0, Id::cpctor, stc, ftype);
if (!(fcp->storage_class & STCdisable))
{
// Build *this = p;
Expression *e = new ThisExp(0);
AssignExp *ea = new AssignExp(0,
new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo())),
new PtrExp(0, new CastExp(0, new AddrExp(0, new IdentifierExp(0, Id::p)), type->mutableOf()->pointerTo()))
);
ea->op = TOKblit;
Statement *s = new ExpStatement(0, ea);
// Build postBlit();
e = new ThisExp(0);
e = new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo()));
e = new DotVarExp(0, e, postblit, 0);
e = new CallExp(0, e);
s = new CompoundStatement(0, s, new ExpStatement(0, e));
fcp->fbody = s;
}
else
fcp->fbody = new ExpStatement(0, (Expression *)NULL);
members->push(fcp);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fcp->semantic(sc);
sc->pop();
s = new CompoundStatement(loc, s, new ExpStatement(loc, e));
fcp->fbody = s;
}
members->push(fcp);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
fcp->semantic(sc);
sc->pop();
return fcp;
}
@@ -579,14 +597,16 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
{
//printf("StructDeclaration::buildPostBlit() %s\n", toChars());
Expression *e = NULL;
StorageClass stc = 0;
StorageClass stc = STCsafe | STCnothrow | STCpure;
Loc declLoc = postblits.dim ? postblits[0]->loc : this->loc;
Loc loc = Loc(); // internal code should have no loc to prevent coverage
Expression *e = NULL;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
assert(v && v->isField());
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
@@ -601,8 +621,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
StructDeclaration *sd = ts->sym;
if (sd->postblit && dim)
{
stc |= sd->postblit->storage_class & STCdisable;
stc = mergeFuncAttrs(stc, sd->postblit->storage_class);
if (stc & STCdisable)
{
e = NULL;
@@ -610,24 +629,24 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
}
// this.v
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
Expression *ex = new ThisExp(loc);
ex = new DotVarExp(loc, ex, v, 0);
if (v->type->toBasetype()->ty == Tstruct)
{ // this.v.postblit()
ex = new DotVarExp(0, ex, sd->postblit, 0);
ex = new CallExp(0, ex);
ex = new DotVarExp(loc, ex, sd->postblit, 0);
ex = new CallExp(loc, ex);
}
else
{
// Typeinfo.postblit(cast(void*)&this.v);
Expression *ea = new AddrExp(0, ex);
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
Expression *ea = new AddrExp(loc, ex);
ea = new CastExp(loc, ea, Type::tvoid->pointerTo());
Expression *et = v->type->getTypeInfo(sc);
et = new DotIdExp(0, et, Id::postblit);
et = new DotIdExp(loc, et, Id::postblit);
ex = new CallExp(0, et, ea);
ex = new CallExp(loc, et, ea);
}
e = Expression::combine(e, ex); // combine in forward order
}
@@ -638,8 +657,8 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
*/
if (e || (stc & STCdisable))
{ //printf("Building __fieldPostBlit()\n");
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, stc, Lexer::idPool("__fieldPostBlit"));
dd->fbody = new ExpStatement(0, e);
PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Lexer::idPool("__fieldPostBlit"));
dd->fbody = new ExpStatement(loc, e);
postblits.shift(dd);
members->push(dd);
dd->semantic(sc);
@@ -655,21 +674,23 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
default:
e = NULL;
stc = STCsafe | STCnothrow | STCpure;
for (size_t i = 0; i < postblits.dim; i++)
{ FuncDeclaration *fd = postblits[i];
stc |= fd->storage_class & STCdisable;
{
FuncDeclaration *fd = postblits[i];
stc = mergeFuncAttrs(stc, fd->storage_class);
if (stc & STCdisable)
{
e = NULL;
break;
}
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd, 0);
ex = new CallExp(0, ex);
Expression *ex = new ThisExp(loc);
ex = new DotVarExp(loc, ex, fd, 0);
ex = new CallExp(loc, ex);
e = Expression::combine(e, ex);
}
PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, stc, Lexer::idPool("__aggrPostBlit"));
dd->fbody = new ExpStatement(0, e);
PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Lexer::idPool("__aggrPostBlit"));
dd->fbody = new ExpStatement(loc, e);
members->push(dd);
dd->semantic(sc);
return dd;
@@ -689,14 +710,17 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
{
//printf("AggregateDeclaration::buildDtor() %s\n", toChars());
Expression *e = NULL;
StorageClass stc = STCsafe | STCnothrow | STCpure;
Loc declLoc = dtors.dim ? dtors[0]->loc : this->loc;
Loc loc = Loc(); // internal code should have no loc to prevent coverage
Expression *e = NULL;
#if DMDV2
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
assert(v && v->isField());
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
@@ -710,27 +734,33 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->dtor && dim)
{ Expression *ex;
{
stc = mergeFuncAttrs(stc, sd->dtor->storage_class);
if (stc & STCdisable)
{
e = NULL;
break;
}
// this.v
ex = new ThisExp(0);
ex = new DotVarExp(0, ex, v, 0);
Expression *ex = new ThisExp(loc);
ex = new DotVarExp(loc, ex, v, 0);
if (v->type->toBasetype()->ty == Tstruct)
{ // this.v.dtor()
ex = new DotVarExp(0, ex, sd->dtor, 0);
ex = new CallExp(0, ex);
ex = new DotVarExp(loc, ex, sd->dtor, 0);
ex = new CallExp(loc, ex);
}
else
{
// Typeinfo.destroy(cast(void*)&this.v);
Expression *ea = new AddrExp(0, ex);
ea = new CastExp(0, ea, Type::tvoid->pointerTo());
Expression *ea = new AddrExp(loc, ex);
ea = new CastExp(loc, ea, Type::tvoid->pointerTo());
Expression *et = v->type->getTypeInfo(sc);
et = new DotIdExp(0, et, Id::destroy);
et = new DotIdExp(loc, et, Id::destroy);
ex = new CallExp(0, et, ea);
ex = new CallExp(loc, et, ea);
}
e = Expression::combine(ex, e); // combine in reverse order
}
@@ -739,10 +769,10 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
/* Build our own "destructor" which executes e
*/
if (e)
if (e || (stc & STCdisable))
{ //printf("Building __fieldDtor()\n");
DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__fieldDtor"));
dd->fbody = new ExpStatement(0, e);
DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Lexer::idPool("__fieldDtor"));
dd->fbody = new ExpStatement(loc, e);
dtors.shift(dd);
members->push(dd);
dd->semantic(sc);
@@ -759,19 +789,82 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
default:
e = NULL;
stc = STCsafe | STCnothrow | STCpure;
for (size_t i = 0; i < dtors.dim; i++)
{ FuncDeclaration *fd = dtors[i];
Expression *ex = new ThisExp(0);
ex = new DotVarExp(0, ex, fd, 0);
ex = new CallExp(0, ex);
{
FuncDeclaration *fd = dtors[i];
stc = mergeFuncAttrs(stc, fd->storage_class);
if (stc & STCdisable)
{
e = NULL;
break;
}
Expression *ex = new ThisExp(loc);
ex = new DotVarExp(loc, ex, fd, 0);
ex = new CallExp(loc, ex);
e = Expression::combine(ex, e);
}
DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__aggrDtor"));
dd->fbody = new ExpStatement(0, e);
DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Lexer::idPool("__aggrDtor"));
dd->fbody = new ExpStatement(loc, e);
members->push(dd);
dd->semantic(sc);
return dd;
}
}
/******************************************
* Create inclusive invariant for struct/class by aggregating
* all the invariants in invs[].
* void __invariant() const [pure nothrow @trusted]
* {
* invs[0](), invs[1](), ...;
* }
*/
FuncDeclaration *AggregateDeclaration::buildInv(Scope *sc)
{
StorageClass stc = STCsafe | STCnothrow | STCpure;
Loc declLoc = this->loc;
Loc loc = Loc(); // internal code should have no loc to prevent coverage
switch (invs.dim)
{
case 0:
return NULL;
case 1:
// Don't return invs[0] so it has uniquely generated name.
/* fall through */
default:
Expression *e = NULL;
StorageClass stcx = 0;
for (size_t i = 0; i < invs.dim; i++)
{
stc = mergeFuncAttrs(stc, invs[i]->storage_class);
if (stc & STCdisable)
{
// What should do?
}
StorageClass stcy = invs[i]->storage_class & (STCshared | STCsynchronized);
if (i == 0)
stcx = stcy;
else if (stcx ^ stcy)
{
#if 1 // currently rejects
error(invs[i]->loc, "mixing invariants with shared/synchronized differene is not supported");
e = NULL;
break;
#endif
}
e = Expression::combine(e, new CallExp(loc, new VarExp(loc, invs[i])));
}
InvariantDeclaration *inv;
inv = new InvariantDeclaration(declLoc, Loc(), stc | stcx, Id::classInvariant);
inv->fbody = new ExpStatement(loc, e);
members->push(inv);
inv->semantic(sc);
return inv;
}
}
+78 -144
View File
@@ -52,7 +52,7 @@ Condition::Condition(Loc loc)
/* ============================================================ */
DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident)
: Condition(0)
: Condition(Loc())
{
this->mod = mod;
this->level = level;
@@ -127,20 +127,83 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
{
static const char* reserved[] =
{
"DigitalMars", "X86", "X86_64",
"Windows", "Win32", "Win64",
"DigitalMars",
"GNU",
"LDC",
"SDC",
"Windows",
"Win32",
"Win64",
"linux",
#if DMDV2
/* Although Posix is predefined by D1, disallowing its
* redefinition breaks makefiles and older builds.
*/
"Posix",
"D_NET",
#endif
"OSX", "FreeBSD",
"OSX",
"FreeBSD",
"OpenBSD",
"NetBSD",
"DragonFlyBSD",
"BSD",
"Solaris",
"LittleEndian", "BigEndian",
"Posix",
"AIX",
"Haiku",
"SkyOS",
"SysV3",
"SysV4",
"Hurd",
"Android",
"Cygwin",
"MinGW",
"X86",
"X86_64",
"ARM",
"ARM_Thumb",
"ARM_SoftFloat",
"ARM_SoftFP",
"ARM_HardFloat",
"AArch64",
"PPC",
"PPC_SoftFloat",
"PPC_HardFloat",
"PPC64",
"IA64",
"MIPS32",
"MIPS64",
"MIPS_O32",
"MIPS_N32",
"MIPS_O64",
"MIPS_N64",
"MIPS_EABI",
"MIPS_SoftFloat",
"MIPS_HardFloat",
"SPARC",
"SPARC_V8Plus",
"SPARC_SoftFloat",
"SPARC_HardFloat",
"SPARC64",
"S390",
"S390X",
"HPPA",
"HPPA64",
"SH",
"SH64",
"Alpha",
"Alpha_SoftFloat",
"Alpha_HardFloat",
"LittleEndian",
"BigEndian",
"D_Coverage",
"D_Ddoc",
"D_InlineAsm_X86",
"D_InlineAsm_X86_64",
"D_LP64",
"D_X32",
"D_HardFloat",
"D_SoftFloat",
"D_PIC",
"D_SIMD",
"D_Version2",
"D_NoBoundsChecks",
"unittest",
"assert",
"all",
"none",
@@ -168,7 +231,7 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident)
void VersionCondition::addGlobalIdent(const char *ident)
{
checkPredefined(0, ident);
checkPredefined(Loc(), ident);
addPredefinedGlobalIdent(ident);
}
@@ -265,7 +328,7 @@ 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->semantic(sc);
Expression *e = exp->ctfeSemantic(sc);
e = resolveProperties(sc, e);
sc->pop();
if (!e->type->checkBoolean())
@@ -296,136 +359,7 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("static if(");
buf->writestring("static if (");
exp->toCBuffer(buf, hgs);
buf->writeByte(')');
}
/**************************** IftypeCondition *******************************/
IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec)
: Condition(loc)
{
this->targ = targ;
this->id = id;
this->tok = tok;
this->tspec = tspec;
}
Condition *IftypeCondition::syntaxCopy()
{
return new IftypeCondition(loc,
targ->syntaxCopy(),
id,
tok,
tspec ? tspec->syntaxCopy() : NULL);
}
int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd)
{
//printf("IftypeCondition::include()\n");
if (inc == 0)
{
if (!sc)
{
error(loc, "iftype conditional cannot be at global scope");
inc = 2;
return 0;
}
Type *t = targ->trySemantic(loc, sc);
if (t)
targ = t;
else
inc = 2; // condition is false
if (!t)
{
}
else if (id && tspec)
{
/* Evaluate to TRUE if targ matches tspec.
* If TRUE, declare id as an alias for the specialized type.
*/
MATCH m;
TemplateTypeParameter tp(loc, id, NULL, NULL);
TemplateParameters parameters;
parameters.setDim(1);
parameters[0] = &tp;
Objects dedtypes;
dedtypes.setDim(1);
m = targ->deduceType(sc, tspec, &parameters, &dedtypes);
if (m == MATCHnomatch ||
(m != MATCHexact && tok == TOKequal))
inc = 2;
else
{
inc = 1;
Type *tded = (Type *)dedtypes[0];
if (!tded)
tded = targ;
Dsymbol *s = new AliasDeclaration(loc, id, tded);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
}
}
else if (id)
{
/* Declare id as an alias for type targ. Evaluate to TRUE
*/
Dsymbol *s = new AliasDeclaration(loc, id, targ);
s->semantic(sc);
sc->insert(s);
if (sd)
s->addMember(sc, sd, 1);
inc = 1;
}
else if (tspec)
{
/* Evaluate to TRUE if targ matches tspec
*/
tspec = tspec->semantic(loc, sc);
//printf("targ = %s\n", targ->toChars());
//printf("tspec = %s\n", tspec->toChars());
if (tok == TOKcolon)
{ if (targ->implicitConvTo(tspec))
inc = 1;
else
inc = 2;
}
else /* == */
{ if (targ->equals(tspec))
inc = 1;
else
inc = 2;
}
}
else
inc = 1;
//printf("inc = %d\n", inc);
}
return (inc == 1);
}
void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("iftype(");
targ->toCBuffer(buf, id, hgs);
if (tspec)
{
if (tok == TOKcolon)
buf->writestring(" : ");
else
buf->writestring(" == ");
tspec->toCBuffer(buf, NULL, hgs);
}
buf->writeByte(')');
}
-17
View File
@@ -54,7 +54,6 @@ struct DebugCondition : DVCondition
{
static void setGlobalLevel(unsigned level);
static void addGlobalIdent(const char *ident);
static void addPredefinedGlobalIdent(const char *ident);
DebugCondition(Module *mod, unsigned level, Identifier *ident);
@@ -87,20 +86,4 @@ struct StaticIfCondition : Condition
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
struct IftypeCondition : Condition
{
/* iftype (targ id tok tspec)
*/
Type *targ;
Identifier *id; // can be NULL
enum TOK tok; // ':' or '=='
Type *tspec; // can be NULL
IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec);
Condition *syntaxCopy();
int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
#endif
+3
View File
@@ -1374,6 +1374,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
e = (*ale->elements)[i];
e->type = type;
e->loc = loc;
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
}
@@ -1392,6 +1393,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
else
{ e = (*ale->elements)[i];
e->type = type;
e->loc = loc;
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
}
@@ -1412,6 +1414,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (ex->isBool(TRUE))
{ e = (*ae->values)[i];
e->type = type;
e->loc = loc;
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
break;
+14 -1
View File
@@ -14,6 +14,7 @@
#pragma once
#endif /* __DMC__ */
#include "arraytypes.h"
/**
Global status of the CTFE engine. Mostly used for performance diagnostics
@@ -44,7 +45,7 @@ struct ClassReferenceExp : Expression
StructLiteralExp *value;
ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
ClassDeclaration *originalClass();
VarDeclaration *getFieldAt(unsigned index);
@@ -53,6 +54,15 @@ struct ClassReferenceExp : Expression
/// Return index of the field, or -1 if not found
/// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(VarDeclaration *v);
#if IN_LLVM
#else
dt_t **toDt(dt_t **pdt);
dt_t **toDtI(dt_t **pdt, int offset);
Symbol* toSymbol();
dt_t **toInstanceDt(dt_t **pdt);
dt_t **toDt2(dt_t **pdt, ClassDeclaration *cd, Dts *dts);
elem *toElem(IRState *irs);
#endif
};
/// Return index of the field, or -1 if not found
@@ -201,6 +211,9 @@ TypeAArray *toBuiltinAAType(Type *t);
*/
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2);
/// True if type is TypeInfo_Class
bool isTypeInfo_Class(Type *type);
/***********************************************
In-place integer operations
***********************************************/
+83 -24
View File
@@ -40,9 +40,9 @@ Expression *ClassReferenceExp::interpret(InterState *istate, CtfeGoal goal)
return this;
}
char *ClassReferenceExp::toChars()
void ClassReferenceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
return value->toChars();
buf->writestring(value->toChars());
}
ClassDeclaration *ClassReferenceExp::originalClass()
@@ -306,6 +306,7 @@ Expression *copyLiteral(Expression *e)
#endif
r->type = e->type;
r->ownedByCtfe = true;
r->origin = ((StructLiteralExp*)e)->origin;
return r;
}
else if (e->op == TOKfunction || e->op == TOKdelegate
@@ -379,13 +380,13 @@ Expression *paintTypeOntoLiteral(Type *type, Expression *lit)
else if (lit->op == TOKarrayliteral)
{
e = new SliceExp(lit->loc, lit,
new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit));
new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit));
}
else if (lit->op == TOKstring)
{
// For strings, we need to introduce another level of indirection
e = new SliceExp(lit->loc, lit,
new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit));
new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit));
}
else if (lit->op == TOKassocarrayliteral)
{
@@ -532,6 +533,16 @@ TypeAArray *toBuiltinAAType(Type *t)
#endif
}
/************** TypeInfo operations ************************************/
// Return true if type is TypeInfo_Class
bool isTypeInfo_Class(Type *type)
{
return type->ty == Tclass &&
(( Type::typeinfo == ((TypeClass*)type)->sym)
|| Type::typeinfo->isBaseOf(((TypeClass*)type)->sym, NULL));
}
/************** Pointer operations ************************************/
// Return true if t is a pointer (not a function pointer)
@@ -574,6 +585,8 @@ Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs)
*ofs = 0;
if (e->op == TOKaddress)
e = ((AddrExp *)e)->e1;
if (e->op == TOKsymoff)
*ofs = ((SymOffExp *)e)->offset;
if (e->op == TOKdotvar)
{
Expression *ex = ((DotVarExp *)e)->e1;
@@ -607,11 +620,19 @@ Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs)
*/
bool pointToSameMemoryBlock(Expression *agg1, Expression *agg2)
{
// For integers cast to pointers, we regard them as non-comparable
// unless they are identical. (This may be overly strict).
if (agg1->op == TOKint64 && agg2->op == TOKint64
&& agg1->toInteger() == agg2->toInteger())
return true;
// Note that type painting can occur with VarExp, so we
// must compare the variables being pointed to.
return agg1 == agg2 ||
(agg1->op == TOKvar && agg2->op == TOKvar &&
((VarExp *)agg1)->var == ((VarExp *)agg2)->var);
((VarExp *)agg1)->var == ((VarExp *)agg2)->var) ||
(agg1->op == TOKsymoff && agg2->op == TOKsymoff &&
((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var);
}
// return e1 - e2 as an integer, or error if not possible
@@ -630,11 +651,16 @@ Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e
{
if (((StringExp *)agg1)->string == ((StringExp *)agg2)->string)
{
Type *pointee = ((TypePointer *)agg1->type)->next;
dinteger_t sz = pointee->size();
return new IntegerExp(loc, (ofs1-ofs2)*sz, type);
Type *pointee = ((TypePointer *)agg1->type)->next;
dinteger_t sz = pointee->size();
return new IntegerExp(loc, (ofs1-ofs2)*sz, type);
}
}
else if (agg1->op == TOKsymoff && agg2->op == TOKsymoff &&
((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var)
{
return new IntegerExp(loc, ofs1-ofs2, type);
}
error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract "
"pointers to two different memory blocks",
e1->toChars(), e2->toChars());
@@ -655,21 +681,36 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
if (eptr->op == TOKaddress)
eptr = ((AddrExp *)eptr)->e1;
Expression *agg1 = getAggregateFromPointer(eptr, &ofs1);
if (agg1->op != TOKstring && agg1->op != TOKarrayliteral)
if (agg1->op == TOKsymoff)
{
if (((SymOffExp *)agg1)->var->type->ty != Tsarray)
{
error(loc, "cannot perform pointer arithmetic on arrays of unknown length at compile time");
return EXP_CANT_INTERPRET;
}
}
else if (agg1->op != TOKstring && agg1->op != TOKarrayliteral)
{
error(loc, "cannot perform pointer arithmetic on non-arrays at compile time");
return EXP_CANT_INTERPRET;
}
ofs2 = e2->toInteger();
Type *pointee = ((TypePointer *)agg1->type)->next;
sinteger_t indx = ofs1;
dinteger_t sz = pointee->size();
Expression *dollar = ArrayLength(Type::tsize_t, agg1);
assert(dollar != EXP_CANT_INTERPRET);
Expression *dollar;
if (agg1->op == TOKsymoff)
{
dollar = ((TypeSArray *)(((SymOffExp *)agg1)->var->type))->dim;
indx = ofs1/sz;
}
else
{
dollar = ArrayLength(Type::tsize_t, agg1);
assert(dollar != EXP_CANT_INTERPRET);
}
dinteger_t len = dollar->toInteger();
Expression *val = agg1;
TypeArray *tar = (TypeArray *)val->type;
sinteger_t indx = ofs1;
if (op == TOKadd || op == TOKaddass || op == TOKplusplus)
indx = indx + ofs2/sz;
else if (op == TOKmin || op == TOKminass || op == TOKminusminus)
@@ -679,17 +720,27 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
error(loc, "CTFE Internal compiler error: bad pointer operation");
return EXP_CANT_INTERPRET;
}
if (val->op != TOKarrayliteral && val->op != TOKstring)
{
error(loc, "CTFE Internal compiler error: pointer arithmetic %s", val->toChars());
return EXP_CANT_INTERPRET;
}
if (indx < 0 || indx > len)
{
error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", indx, len);
return EXP_CANT_INTERPRET;
}
if (agg1->op == TOKsymoff)
{
SymOffExp *se = new SymOffExp(loc, ((SymOffExp *)agg1)->var, indx*sz);
se->type = type;
return se;
}
Expression *val = agg1;
if (val->op != TOKarrayliteral && val->op != TOKstring)
{
error(loc, "CTFE Internal compiler error: pointer arithmetic %s", val->toChars());
return EXP_CANT_INTERPRET;
}
IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t);
IndexExp *ie = new IndexExp(loc, val, ofs);
ie->type = type;
@@ -1408,7 +1459,9 @@ int ctfeIdentity(Loc loc, enum TOK op, Expression *e1, Expression *e2)
int ctfeCmp(Loc loc, enum TOK op, Expression *e1, Expression *e2)
{
int n;
if (e1->type->isString() && e2->type->isString())
Type *t1 = e1->type->toBasetype();
Type *t2 = e2->type->toBasetype();
if (t1->isString() && t2->isString())
{
int cmp = ctfeRawCmp(loc, e1, e2);
switch (op)
@@ -1431,15 +1484,15 @@ int ctfeCmp(Loc loc, enum TOK op, Expression *e1, Expression *e2)
assert(0);
}
}
else if (e1->type->isreal())
else if (t1->isreal())
{
n = realCmp(op, e1->toReal(), e2->toReal());
}
else if (e1->type->isimaginary())
else if (t1->isimaginary())
{
n = realCmp(op, e1->toImaginary(), e2->toImaginary());
}
else if (e1->type->isunsigned() || e2->type->isunsigned())
else if (t1->isunsigned() || t2->isunsigned())
{
n = intUnsignedCmp(op, e1->toInteger(), e2->toInteger());
}
@@ -1598,6 +1651,10 @@ Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e)
else
return new NullExp(loc, to);
}
// Allow TypeInfo type painting
if (isTypeInfo_Class(e->type) && e->type->implicitConvTo(to))
return paintTypeOntoLiteral(to, e);
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());
@@ -1765,7 +1822,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae,
Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType,
Expression *oldval, size_t oldlen, size_t newlen)
{
Type *elemType = elemType = arrayType->next;
Type *elemType = arrayType->next;
assert(elemType);
Expression *defaultElem = elemType->defaultInitLiteral(loc);
Expressions *elements = new Expressions();
@@ -1895,6 +1952,8 @@ bool isCtfeValueValid(Expression *newval)
{
if (((SymOffExp *)newval)->var->isFuncDeclaration())
return true;
if (((SymOffExp *)newval)->var->isDataseg())
return true; // pointer to static variable
}
if (newval->op == TOKint64 || newval->op == TOKfloat64 ||
+215 -167
View File
@@ -24,12 +24,14 @@
#include "expression.h"
#include "statement.h"
#include "hdrgen.h"
#include "ctfe.h"
#include "target.h"
AggregateDeclaration *isAggregate(Type *t); // from opover.c
void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad)
{
if (!ad->isnested)
if (!ad->isNested())
return;
Dsymbol *s = sc->func;
@@ -82,6 +84,7 @@ Declaration::Declaration(Identifier *id)
linkage = LINKdefault;
inuse = 0;
sem = SemanticStart;
mangleOverride = NULL;
}
void Declaration::semantic(Scope *sc)
@@ -137,18 +140,20 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int fl
if (v && v->canassign)
return 2;
if ((sc->flags & SCOPEcontract) && isParameter())
if (isParameter() || isResult())
{
if (!flag) error(loc, "cannot modify parameter '%s' in contract", toChars());
return 0;
}
if ((sc->flags & SCOPEcontract) && isResult())
{
if (!flag) error(loc, "cannot modify result '%s' in contract", toChars());
return 0;
for (Scope *scx = sc; scx; scx = scx->enclosing)
{
if (scx->func == parent && (scx->flags & SCOPEcontract))
{
const char *s = isParameter() && parent->ident != Id::ensure ? "parameter" : "result";
if (!flag) error(loc, "cannot modify %s '%s' in contract", s, toChars());
return 0;
}
}
}
if (v && isCtorinit())
if (v && (isCtorinit() || isField()))
{ // It's only modifiable if inside the right constructor
if ((storage_class & (STCforeach | STCref)) == (STCforeach | STCref))
return 2;
@@ -242,7 +247,7 @@ Type *TupleDeclaration::getType()
tupletype = new TypeTuple(args);
if (hasdeco)
return tupletype->semantic(0, NULL);
return tupletype->semantic(Loc(), NULL);
}
return tupletype;
@@ -387,7 +392,7 @@ void TypedefDeclaration::semantic2(Scope *sc)
Initializer *savedinit = init;
int errors = global.errors;
init = init->semantic(sc, basetype, INITinterpret);
if (errors != global.errors)
if (errors != global.errors || init->isErrorInitializer())
{
init = savedinit;
return;
@@ -535,6 +540,12 @@ void AliasDeclaration::semantic(Scope *sc)
* try to alias y to 3.
*/
s = type->toDsymbol(sc);
if (s && s == this)
{
error("cannot resolve");
s = NULL;
type = Type::terror;
}
if (s
#if DMDV2
&& ((s->getType() && type->equals(s->getType())) || s->isEnumMember())
@@ -576,7 +587,7 @@ void AliasDeclaration::semantic(Scope *sc)
//printf("\talias resolved to type %s\n", type->toChars());
}
if (overnext)
ScopeDsymbol::multiplyDefined(0, overnext, this);
ScopeDsymbol::multiplyDefined(Loc(), overnext, this);
this->inSemantic = 0;
if (global.gag && errors != global.errors)
@@ -605,7 +616,7 @@ void AliasDeclaration::semantic(Scope *sc)
fa->importprot = importprot;
#endif
if (!fa->overloadInsert(overnext))
ScopeDsymbol::multiplyDefined(0, overnext, f);
ScopeDsymbol::multiplyDefined(Loc(), overnext, f);
overnext = NULL;
s = fa;
s->parent = sc->parent;
@@ -623,7 +634,7 @@ void AliasDeclaration::semantic(Scope *sc)
}
}
if (overnext)
ScopeDsymbol::multiplyDefined(0, overnext, this);
ScopeDsymbol::multiplyDefined(Loc(), overnext, this);
if (s == this)
{
assert(global.errors);
@@ -701,9 +712,9 @@ Dsymbol *AliasDeclaration::toAlias()
}
else if (aliassym || type->deco)
; // semantic is already done.
else if (import)
else if (import && import->scope)
{
/* If this is an internal alias for selective import,
/* If this is an internal alias for selective/renamed import,
* resolve it under the correct scope.
*/
import->semantic(NULL);
@@ -851,8 +862,10 @@ void VarDeclaration::semantic(Scope *sc)
// return;
// sem = SemanticIn;
Scope *scx = NULL;
if (scope)
{ sc = scope;
scx = sc;
scope = NULL;
}
@@ -874,6 +887,11 @@ void VarDeclaration::semantic(Scope *sc)
if (!type)
{ inuse++;
// Infering the type requires running semantic,
// so mark the scope as ctfe if required
if (storage_class & (STCmanifest | STCstatic))
sc->needctfe++;
//printf("inferring type for %s with init %s\n", toChars(), init->toChars());
ArrayInitializer *ai = init->isArrayInitializer();
if (ai)
@@ -895,6 +913,8 @@ void VarDeclaration::semantic(Scope *sc)
else
type = init->inferType(sc);
if (storage_class & (STCmanifest | STCstatic))
sc->needctfe--;
// type = type->semantic(loc, sc);
inuse--;
@@ -914,7 +934,9 @@ void VarDeclaration::semantic(Scope *sc)
else
{ if (!originalType)
originalType = type->syntaxCopy();
inuse++;
type = type->semantic(loc, sc);
inuse--;
}
//printf(" semantic type = %s\n", type ? type->toChars() : "null");
@@ -968,6 +990,9 @@ void VarDeclaration::semantic(Scope *sc)
FuncDeclaration *fd = parent->isFuncDeclaration();
Type *tb = type->toBasetype();
Type *tbn = tb;
while (tbn->ty == Tsarray)
tbn = tbn->nextOf()->toBasetype();
if (tb->ty == Tvoid && !(storage_class & STClazy))
{
if (inferred)
@@ -1004,7 +1029,7 @@ void VarDeclaration::semantic(Scope *sc)
size_t nelems = Parameter::dim(tt->arguments);
Objects *exps = new Objects();
exps->setDim(nelems);
Expression *ie = init ? init->toExpression() : NULL;
Expression *ie = (init && !init->isVoidInitializer()) ? init->toExpression() : NULL;
if (ie) ie = ie->semantic(sc);
if (nelems > 0 && ie)
@@ -1040,6 +1065,7 @@ void VarDeclaration::semantic(Scope *sc)
iexps->remove(pos);
iexps->insert(pos, te->exps);
(*iexps)[pos] = Expression::combine(te->e0, (*iexps)[pos]);
goto Lexpand1;
}
else if (isAliasThisTuple(e))
@@ -1095,11 +1121,13 @@ void VarDeclaration::semantic(Scope *sc)
Lnomatch:
if (ie && ie->op == TOKtuple)
{ size_t tedim = ((TupleExp *)ie)->exps->dim;
{
TupleExp *te = (TupleExp *)ie;
size_t tedim = te->exps->dim;
if (tedim != nelems)
{ ::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems);
for (size_t u = tedim; u < nelems; u++) // fill dummy expression
((TupleExp *)ie)->exps->push(new ErrorExp());
te->exps->push(new ErrorExp());
}
}
@@ -1114,7 +1142,11 @@ Lnomatch:
Expression *einit = ie;
if (ie && ie->op == TOKtuple)
{ einit = (*((TupleExp *)ie)->exps)[i];
{
TupleExp *te = (TupleExp *)ie;
einit = (*te->exps)[i];
if (i == 0)
einit = Expression::combine(te->e0, einit);
}
Initializer *ti = init;
if (einit)
@@ -1164,7 +1196,10 @@ Lnomatch:
else if (type->isWild())
storage_class |= STCwild;
if (isSynchronized())
if (storage_class & (STCmanifest | STCstatic | STCgshared))
{
}
else if (isSynchronized())
{
error("variable %s cannot be synchronized", toChars());
}
@@ -1191,19 +1226,19 @@ Lnomatch:
{
#if DMDV2
assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared)));
if (storage_class & (STCconst | STCimmutable) && init)
if (storage_class & (STCconst | STCimmutable) && init &&
global.params.vfield)
{
if (!tb->isTypeBasic())
storage_class |= STCstatic;
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);
}
else
#endif
{
storage_class |= STCfield;
#if DMDV2
if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor ||
tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor)
if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor ||
tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor)
aad->noDefaultCtor = TRUE;
#endif
}
@@ -1266,11 +1301,11 @@ Lnomatch:
}
}
if (!(storage_class & (STCctfe | STCref)) && tb->ty == Tstruct &&
((TypeStruct *)tb)->sym->noDefaultCtor)
if (!(storage_class & (STCctfe | STCref)) && tbn->ty == Tstruct &&
((TypeStruct *)tbn)->sym->noDefaultCtor)
{
if (!init)
{ if (storage_class & STCfield)
{ if (isField())
/* For fields, we'll check the constructor later to make sure it is initialized
*/
storage_class |= STCnodefaultctor;
@@ -1307,7 +1342,7 @@ Lnomatch:
error("manifest constants must have initializers");
enum TOK op = TOKconstruct;
if (!init && !sc->inunion && !isStatic() && fd &&
if (!init && !sc->inunion && !(storage_class & (STCstatic | STCgshared | STCextern)) && fd &&
(!(storage_class & (STCfield | STCin | STCforeach | STCparameter | STCresult))
|| (storage_class & STCout)) &&
type->size() != 0)
@@ -1451,7 +1486,7 @@ Lnomatch:
if (t->ty != Tsarray)
break;
dim *= ((TypeSArray *)t)->dim->toInteger();
e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
e1->type = new TypeSArray(t->nextOf(), new IntegerExp(Loc(), dim, Type::tindex));
}
}
e1 = new SliceExp(loc, e1, NULL, NULL);
@@ -1478,7 +1513,7 @@ Lnomatch:
/* Look for form of constructor call which is:
* *__ctmp.ctor(arguments...)
*/
if (1)
if ((*pinit)->type->implicitConvTo(t))
{ CallExp *ce = (CallExp *)(*pinit);
if (ce->e1->op == TOKdotvar)
{ DotVarExp *dve = (DotVarExp *)ce->e1;
@@ -1586,6 +1621,11 @@ Lnomatch:
init = init->semantic(sc, type, INITinterpret);
}
}
else if (parent->isAggregateDeclaration())
{
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
}
else if (storage_class & (STCconst | STCimmutable | STCmanifest) ||
type->isConst() || type->isImmutable())
{
@@ -1597,16 +1637,18 @@ Lnomatch:
if (!global.errors && !inferred)
{
unsigned errors = global.startGagging();
Expression *exp;
Initializer *i2 = init;
unsigned errors = global.errors;
inuse++;
#if DMDV2
if (ei)
{
Expression *exp;
exp = ei->exp->syntaxCopy();
exp = exp->semantic(sc);
if (isDataseg() || (storage_class & STCmanifest))
exp = exp->ctfeSemantic(sc);
else
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
#if DMDV2
Type *tb = type->toBasetype();
Type *ti = exp->type->toBasetype();
@@ -1648,77 +1690,22 @@ Lnomatch:
;
}
}
// Look for implicit constructor call
if (tb->ty == Tstruct &&
!(ti->ty == Tstruct && tb->toDsymbol(sc) == ti->toDsymbol(sc)) &&
!exp->implicitConvTo(type))
{
StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->ctor)
{ // Look for constructor first
// Rewrite as e1.ctor(arguments)
Expression *e;
e = new StructLiteralExp(loc, sd, NULL, NULL);
e = new DotIdExp(loc, e, Id::ctor);
e = new CallExp(loc, e, exp);
e = e->semantic(sc);
exp = e->ctfeInterpret();
}
}
ei->exp = exp;
}
#endif
exp = exp->implicitCastTo(sc, type);
}
else if (si || ai)
{ i2 = init->syntaxCopy();
i2 = i2->semantic(sc, type, INITinterpret);
}
init = init->semantic(sc, type, INITinterpret);
inuse--;
if (global.endGagging(errors)) // if errors happened
if (global.errors > errors)
{
#if DMDV2
/* Save scope for later use, to try again
*/
scope = new Scope(*sc);
scope->setNoFree();
#endif
init = new ErrorInitializer();
type = Type::terror;
}
else if (ei)
{
if (isDataseg() || (storage_class & STCmanifest))
exp = exp->ctfeInterpret();
else
exp = exp->optimize(WANTvalue);
switch (exp->op)
{
case TOKint64:
case TOKfloat64:
case TOKstring:
case TOKarrayliteral:
case TOKassocarrayliteral:
case TOKstructliteral:
case TOKnull:
ei->exp = exp; // no errors, keep result
break;
default:
#if DMDV2
/* Save scope for later use, to try again
*/
scope = new Scope(*sc);
scope->setNoFree();
#endif
break;
}
}
else
init = i2; // no errors, keep result
}
}
else if (parent->isAggregateDeclaration())
{
scope = new Scope(*sc);
scope->setNoFree();
else
{
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
}
}
sc = sc->pop();
}
@@ -1738,6 +1725,9 @@ Ldtor:
}
sem = SemanticDone;
if (type->toBasetype()->ty == Terror)
errors = true;
}
void VarDeclaration::semantic2(Scope *sc)
@@ -1781,6 +1771,55 @@ void VarDeclaration::semantic2(Scope *sc)
init = init->semantic(sc, type, INITinterpret);
inuse--;
}
if (storage_class & STCmanifest)
{
#if 0
if ((type->ty == Tclass)&&type->isMutable())
{
error("is mutable. Only const and immutable class enum are allowed, not %s", type->toChars());
}
else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct && type->nextOf()->isMutable())
{
ExpInitializer *ei = init->isExpInitializer();
if (ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral)
{
error("is a pointer to mutable struct. Only pointers to const or immutable struct enum are allowed, not %s", type->toChars());
}
}
#else
if (type->ty == Tclass && init)
{
ExpInitializer *ei = init->isExpInitializer();
if (ei->exp->op == TOKclassreference)
error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead.");
}
else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct)
{
ExpInitializer *ei = init->isExpInitializer();
if (ei && ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral)
{
error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead.");
}
}
#endif
}
else if (init && isThreadlocal())
{
if ((type->ty == Tclass)&&type->isMutable()&&!type->isShared())
{
ExpInitializer *ei = init->isExpInitializer();
if (ei->exp->op == TOKclassreference)
error("is mutable. Only const or immutable class thread local variable are allowed, not %s", type->toChars());
}
else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct && type->nextOf()->isMutable() &&!type->nextOf()->isShared())
{
ExpInitializer *ei = init->isExpInitializer();
if (ei && ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral)
{
error("is a pointer to mutable struct. Only pointers to const, immutable or shared struct thread local variable are allowed are allowed, not %s", type->toChars());
}
}
}
sem = Semantic2Done;
}
@@ -1803,7 +1842,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
return;
}
if (!(storage_class & STCfield))
if (!isField())
return;
assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls)));
@@ -1824,32 +1863,9 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
{ // References are the size of a pointer
t = Type::tvoidptr;
}
if (t->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)t;
#if DMDV2
if (ts->sym == ad)
{
ad->error("cannot have field %s with same struct type", toChars());
}
#endif
if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope)
ts->sym->semantic(NULL);
if (ts->sym->sizeok != SIZEOKdone)
{
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}
}
if (t->ty == Tident)
if (t->ty == Tstruct || t->ty == Tsarray)
{
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}
#if DMDV2
else if (t->ty == Tsarray)
{
Type *tv = t->toBasetype();
Type *tv = t;
while (tv->ty == Tsarray)
{
tv = tv->nextOf()->toBasetype();
@@ -1857,17 +1873,29 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
if (tv->ty == Tstruct)
{
TypeStruct *ts = (TypeStruct *)tv;
if (ad == ts->sym)
if (ts->sym == ad)
{
ad->error("cannot have field %s with same struct type", toChars());
const char *s = (t->ty == Tsarray) ? "static array of " : "";
ad->error("cannot have field %s with %ssame struct type", toChars(), s);
}
if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope)
ts->sym->semantic(NULL);
if (ts->sym->sizeok != SIZEOKdone)
{
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}
}
}
#endif
if (t->ty == Tident)
{
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}
unsigned memsize = t->size(loc); // size of member
unsigned memalignsize = t->alignsize(); // size of member for alignment purposes
unsigned memalignsize = Target::fieldalign(t); // size of member for alignment purposes
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment,
&ad->structsize, &ad->alignsize, isunion);
@@ -1936,9 +1964,6 @@ AggregateDeclaration *VarDeclaration::isThis()
if (!(storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter |
STCtls | STCgshared | STCctfe)))
{
if ((storage_class & (STCconst | STCimmutable | STCwild)) && init)
return NULL;
for (Dsymbol *s = this; s; s = s->parent)
{
ad = s->isMember();
@@ -1953,7 +1978,12 @@ AggregateDeclaration *VarDeclaration::isThis()
int VarDeclaration::needThis()
{
//printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
return storage_class & STCfield;
return isField();
}
int VarDeclaration::isExport()
{
return protection == PROTexport;
}
int VarDeclaration::isImportedSymbol()
@@ -1967,7 +1997,7 @@ int VarDeclaration::isImportedSymbol()
void VarDeclaration::checkCtorConstInit()
{
#if 0 /* doesn't work if more than one static ctor */
if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
if (ctorinit == 0 && isCtorinit() && !isField())
error("missing initializer in static constructor for const variable");
#endif
}
@@ -2021,6 +2051,16 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
{
fld->tok = TOKdelegate;
/* This is necessary to avoid breaking tests for 8751 & 8793.
* See: compilable/testInference.d
*/
if (type->isMutable() || // mutable variable
!type->implicitConvTo(type->invariantOf()) || // has any mutable indirections
!fdv->isPureBypassingInference()) // does not belong to pure function
{
fld->setImpure(); // Bugzilla 9415
}
}
}
@@ -2072,21 +2112,30 @@ ExpInitializer *VarDeclaration::getExpInitializer()
* Otherwise, return NULL.
*/
Expression *VarDeclaration::getConstInitializer()
Expression *VarDeclaration::getConstInitializer(bool needFullType)
{
if ((isConst() || isImmutable() || storage_class & STCmanifest) &&
storage_class & STCinit)
assert(type && init);
// Ungag errors when not speculative
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging())
{
ExpInitializer *ei = getExpInitializer();
if (ei)
return ei->exp;
else if (init)
{
return init->toExpression();
}
Dsymbol *sym = toParent()->isAggregateDeclaration();
if (sym && !sym->isSpeculative())
global.gag = 0;
}
return NULL;
if (scope)
{
inuse++;
init->semantic(scope, type, INITinterpret);
scope = NULL;
inuse--;
}
Expression *e = init->toExpression(needFullType ? type : NULL);
global.gag = oldgag;
return e;
}
/*************************************
@@ -2102,7 +2151,7 @@ int VarDeclaration::canTakeAddressOf()
*/
if ((isConst() || isImmutable()) &&
storage_class & STCinit &&
(!(storage_class & (STCstatic | STCextern)) || (storage_class & STCfield)) &&
(!(storage_class & (STCstatic | STCextern)) || isField()) &&
(!parent || toParent()->isModule() || toParent()->isTemplateInstance()) &&
type->toBasetype()->isTypeBasic()
)
@@ -2287,15 +2336,24 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc)
void ObjectNotFound(Identifier *id)
{
Type::error(0, "%s not found. object.d may be incorrectly installed or corrupt.", id->toChars());
Type::error(Loc(), "%s not found. object.d may be incorrectly installed or corrupt.", id->toChars());
fatal();
}
/********************************* ClassInfoDeclaration ****************************/
SymbolDeclaration::SymbolDeclaration(Loc loc, StructDeclaration *dsym)
: Declaration(dsym->ident)
{
this->loc = loc;
this->dsym = dsym;
storage_class |= STCconst;
}
/********************************* ClassInfoDeclaration ****************************/
ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd)
: VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL)
: VarDeclaration(Loc(), ClassDeclaration::classinfo->type, cd->ident, NULL)
{
this->cd = cd;
storage_class = STCstatic | STCgshared;
@@ -2314,7 +2372,7 @@ void ClassInfoDeclaration::semantic(Scope *sc)
/********************************* ModuleInfoDeclaration ****************************/
ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod)
: VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL)
: VarDeclaration(Loc(), Module::moduleinfo->type, mod->ident, NULL)
{
this->mod = mod;
storage_class = STCstatic | STCgshared;
@@ -2333,7 +2391,7 @@ void ModuleInfoDeclaration::semantic(Scope *sc)
/********************************* TypeInfoDeclaration ****************************/
TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal)
: VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
: VarDeclaration(Loc(), Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL)
{
this->tinfo = tinfo;
storage_class = STCstatic | STCgshared;
@@ -2583,13 +2641,3 @@ Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s)
assert(0); // should never be produced by syntax
return NULL;
}
/********************** StaticStructInitDeclaration ***************************/
StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym)
: Declaration(new Identifier("", TOKidentifier))
{
this->loc = loc;
this->dsym = dsym;
storage_class |= STCconst;
}
+47 -47
View File
@@ -110,10 +110,6 @@ enum PURE;
STCmanifest | STCimmutable | STCshared | STCnothrow | STCpure | STCref | STCtls | \
STCgshared | STCproperty | STCsafe | STCtrusted | STCsystem | STCdisable)
#ifdef BUG6652
#define STCbug6652 0x800000000000LL //
#endif
struct Match
{
int count; // number of matches found
@@ -124,11 +120,13 @@ struct Match
};
void overloadResolveX(Match *m, FuncDeclaration *f,
Expression *ethis, Expressions *arguments);
Type *tthis, Expressions *arguments);
int overloadApply(FuncDeclaration *fstart,
int (*fp)(void *, FuncDeclaration *),
void *param);
void ObjectNotFound(Identifier *id);
enum Semantic
{
SemanticStart, // semantic has not been run
@@ -147,11 +145,7 @@ struct Declaration : Dsymbol
enum PROT protection;
enum LINK linkage;
int inuse; // used to detect cycles
#ifdef IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
const char *mangleOverride; // overridden symbol with pragma(mangle, "...")
enum Semantic sem;
Declaration(Identifier *id);
@@ -164,32 +158,33 @@ struct Declaration : Dsymbol
void emitComment(Scope *sc);
void toJson(JsonOut *json);
void jsonProperties(JsonOut *json);
virtual void jsonProperties(JsonOut *json);
void toDocBuffer(OutBuffer *buf, Scope *sc);
char *mangle(bool isv = false);
int isStatic() { return storage_class & STCstatic; }
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();
int isCtorinit() { return storage_class & STCctorinit; }
int isFinal() { return storage_class & STCfinal; }
int isAbstract() { return storage_class & STCabstract; }
int isConst() { return storage_class & STCconst; }
int isImmutable() { return storage_class & STCimmutable; }
int isWild() { return storage_class & STCwild; }
int isAuto() { return storage_class & STCauto; }
int isScope() { return storage_class & STCscope; }
int isSynchronized() { return storage_class & STCsynchronized; }
int isParameter() { return storage_class & STCparameter; }
int isDeprecated() { return storage_class & STCdeprecated; }
int isOverride() { return storage_class & STCoverride; }
StorageClass isResult() { return storage_class & STCresult; }
bool isCtorinit() { return (storage_class & STCctorinit) != 0; }
bool isFinal() { return (storage_class & STCfinal) != 0; }
bool isAbstract() { return (storage_class & STCabstract) != 0; }
bool isConst() { return (storage_class & STCconst) != 0; }
bool isImmutable() { return (storage_class & STCimmutable) != 0; }
bool isWild() { return (storage_class & STCwild) != 0; }
bool isAuto() { return (storage_class & STCauto) != 0; }
bool isScope() { return (storage_class & STCscope) != 0; }
bool isSynchronized() { return (storage_class & STCsynchronized) != 0; }
bool isParameter() { return (storage_class & STCparameter) != 0; }
bool isDeprecated() { return (storage_class & STCdeprecated) != 0; }
bool isOverride() { return (storage_class & STCoverride) != 0; }
bool isResult() { return (storage_class & STCresult) != 0; }
bool isField() { return (storage_class & STCfield) != 0; }
int isIn() { return storage_class & STCin; }
int isOut() { return storage_class & STCout; }
int isRef() { return storage_class & STCref; }
bool isIn() { return (storage_class & STCin) != 0; }
bool isOut() { return (storage_class & STCout) != 0; }
bool isRef() { return (storage_class & STCref) != 0; }
enum PROT prot();
@@ -236,7 +231,7 @@ struct TypedefDeclaration : Declaration
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void semantic2(Scope *sc);
char *mangle(bool isv = false);
const char *mangle(bool isv = false);
const char *kind();
Type *getType();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -341,6 +336,7 @@ struct VarDeclaration : Declaration
Initializer *hinit;
AggregateDeclaration *isThis();
int needThis();
int isExport();
int isImportedSymbol();
int isDataseg();
int isThreadlocal();
@@ -352,17 +348,16 @@ struct VarDeclaration : Declaration
#endif
Expression *callScopeDtor(Scope *sc);
ExpInitializer *getExpInitializer();
Expression *getConstInitializer();
Expression *getConstInitializer(bool needFullType = true);
void checkCtorConstInit();
void checkNestedReference(Scope *sc, Loc loc);
Dsymbol *toAlias();
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
Symbol *toSymbol();
int cvMember(unsigned char *p);
#endif
const char *mangle(bool isv = false);
// Eliminate need for dynamic_cast
VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; }
@@ -390,20 +385,20 @@ struct VarDeclaration : Declaration
/**************************************************************/
// LDC uses this to denote static struct initializers
// This is a shell around a back end symbol
struct StaticStructInitDeclaration : Declaration
struct SymbolDeclaration : Declaration
{
StructDeclaration *dsym;
StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym);
SymbolDeclaration(Loc loc, StructDeclaration *dsym);
#if IN_DMD
Symbol *toSymbol();
#endif
// Eliminate need for dynamic_cast
StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; }
SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; }
};
struct ClassInfoDeclaration : VarDeclaration
@@ -785,6 +780,7 @@ struct FuncDeclaration : Declaration
#else
bool isArrayOp; // !=0 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
@@ -852,7 +848,7 @@ struct FuncDeclaration : Declaration
int findVtblIndex(Dsymbols *vtbl, int dim);
int overloadInsert(Dsymbol *s);
FuncDeclaration *overloadExactMatch(Type *t);
FuncDeclaration *overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags = 0);
FuncDeclaration *overloadResolve(Loc loc, Type *tthis, Expressions *arguments, int flags = 0);
MATCH leastAsSpecialized(FuncDeclaration *g);
LabelDsymbol *searchLabel(Identifier *ident);
AggregateDeclaration *isThis();
@@ -860,8 +856,9 @@ struct FuncDeclaration : Declaration
int getLevel(Loc loc, Scope *sc, FuncDeclaration *fd); // lexical nesting level difference
void appendExp(Expression *e);
void appendState(Statement *s);
char *mangle(bool isv = false);
const char *mangle(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();
@@ -879,6 +876,8 @@ struct FuncDeclaration : Declaration
bool isSafeBypassingInference();
int isTrusted();
bool setUnsafe();
bool isolateReturn();
bool parametersIntersect(Type *t);
virtual int isNested();
int needThis();
int isVirtualMethod();
@@ -953,11 +952,11 @@ struct FuncDeclaration : Declaration
};
#if DMDV2
FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
Objects *tiargs,
Expression *ethis,
Type *tthis,
Expressions *arguments,
int flags);
int flags = 0);
#endif
struct FuncAliasDeclaration : FuncDeclaration
@@ -973,7 +972,7 @@ struct FuncAliasDeclaration : FuncDeclaration
#if IN_DMD
Symbol *toSymbol();
#endif
char *mangle(bool isv = false) { return toAliasFunc()->mangle(isv); }
const char *mangle(bool isv = false) { return toAliasFunc()->mangle(isv); }
FuncDeclaration *toAliasFunc();
};
@@ -1014,7 +1013,6 @@ struct CtorDeclaration : FuncDeclaration
int isVirtual();
int addPreInvariant();
int addPostInvariant();
bool isImplicit; // implicitly generated ctor
CtorDeclaration *isCtorDeclaration() { return this; }
};
@@ -1040,7 +1038,7 @@ struct PostBlitDeclaration : FuncDeclaration
struct DtorDeclaration : FuncDeclaration
{
DtorDeclaration(Loc loc, Loc endloc);
DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -1114,7 +1112,7 @@ struct SharedStaticDtorDeclaration : StaticDtorDeclaration
struct InvariantDeclaration : FuncDeclaration
{
InvariantDeclaration(Loc loc, Loc endloc);
InvariantDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id = NULL);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
int isVirtual();
@@ -1128,13 +1126,15 @@ struct InvariantDeclaration : FuncDeclaration
struct UnitTestDeclaration : FuncDeclaration
{
UnitTestDeclaration(Loc loc, Loc endloc);
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();
void emitComment(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
UnitTestDeclaration *isUnitTestDeclaration() { return this; }
+28 -33
View File
@@ -19,6 +19,7 @@
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
#include "init.h"
#if IN_LLVM
#include "init.h"
@@ -115,41 +116,11 @@ int lambdaCheckForNestedRef(Expression *e, void *param)
*/
switch (e->op)
{
#if IN_LLVM
// We also need to consider the initializers of VarDeclarations in
// DeclarationExps, such as generated for postblit invocation for
// function parameters.
//
// Without this check, e.g. the nested reference to a in the delegate
// create for the lazy argument is not picked up in the following case:
// ---
// struct HasPostblit { this(this) {} }
// struct Foo { HasPostblit _data; }
// void receiver(Foo) {}
// void lazyFunc(E)(lazy E e) { e(); }
// void test() { Foo a; lazyFunc(receiver(a)); }
// ---
case TOKdeclaration:
{ DeclarationExp *de = (DeclarationExp *)e;
if (VarDeclaration *vd = de->declaration->isVarDeclaration())
{
if (vd->init)
{
if (ExpInitializer* ei = vd->init->isExpInitializer())
{
ei->exp->apply(&lambdaCheckForNestedRef, sc);
}
// TODO: Other classes of initializers?
}
}
break;
}
#endif
case TOKsymoff:
{ SymOffExp *se = (SymOffExp *)e;
VarDeclaration *v = se->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
v->checkNestedReference(sc, Loc());
break;
}
@@ -157,7 +128,7 @@ int lambdaCheckForNestedRef(Expression *e, void *param)
{ VarExp *ve = (VarExp *)e;
VarDeclaration *v = ve->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
v->checkNestedReference(sc, Loc());
break;
}
@@ -166,7 +137,31 @@ int lambdaCheckForNestedRef(Expression *e, void *param)
{ ThisExp *te = (ThisExp *)e;
VarDeclaration *v = te->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
v->checkNestedReference(sc, Loc());
break;
}
case TOKdeclaration:
{ DeclarationExp *de = (DeclarationExp *)e;
VarDeclaration *v = de->declaration->isVarDeclaration();
if (v)
{
v->checkNestedReference(sc, Loc());
/* Some expressions cause the frontend to create a temporary.
* For example, structs with cpctors replace the original
* expression e with:
* __cpcttmp = __cpcttmp.cpctor(e);
*
* In this instance, we need to ensure that the original
* expression e does not have any nested references by
* checking the declaration initializer too.
*/
if (v->init && v->init->isExpInitializer())
{ Expression *ie = v->init->toExpression();
ie->apply (&lambdaCheckForNestedRef, param);
}
}
break;
}
+162 -85
View File
@@ -106,9 +106,10 @@ Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, size_t len);
int isIdStart(unsigned char *p);
int isIdTail(unsigned char *p);
int isIndentWS(unsigned char *p);
int utfStride(unsigned char *p);
static unsigned char ddoc_default[] = "\
static const char ddoc_default[] = "\
DDOC = <html><head>\n\
<META http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n\
<title>$(TITLE)</title>\n\
@@ -140,6 +141,7 @@ LINK2 = <a href=\"$1\">$+</a>\n\
LPAREN= (\n\
RPAREN= )\n\
DOLLAR= $\n\
DEPRECATED= $0\n\
\n\
RED = <font color=red>$0</font>\n\
BLUE = <font color=blue>$0</font>\n\
@@ -199,11 +201,11 @@ ESCAPES = /</&lt;/\n\
/&/&amp;/\n\
";
static char ddoc_decl_s[] = "$(DDOC_DECL ";
static char ddoc_decl_e[] = ")\n";
static const char ddoc_decl_s[] = "$(DDOC_DECL ";
static const char ddoc_decl_e[] = ")\n";
static char ddoc_decl_dd_s[] = "$(DDOC_DECL_DD ";
static char ddoc_decl_dd_e[] = ")\n";
static const char ddoc_decl_dd_s[] = "$(DDOC_DECL_DD ";
static const char ddoc_decl_dd_e[] = ")\n";
/****************************************************
@@ -473,8 +475,92 @@ void escapeStrayParenthesis(OutBuffer *buf, size_t start, Loc loc)
}
}
static bool emitAnchorName(OutBuffer *buf, Dsymbol *s)
{
if (!s || s->isPackage() || s->isModule())
return false;
TemplateDeclaration *td;
bool dot;
// Add parent names first
dot = emitAnchorName(buf, s->parent);
// Eponymous template members can share the parent anchor name
if (s->parent && (td = s->parent->isTemplateDeclaration()) != NULL &&
td->onemember == s)
return dot;
if (dot)
buf->writeByte('.');
// Use "this" not "__ctor"
if (s->isCtorDeclaration() || ((td = s->isTemplateDeclaration()) != NULL &&
td->onemember && td->onemember->isCtorDeclaration()))
buf->writestring("this");
else
{
/* We just want the identifier, not overloads like TemplateDeclaration::toChars.
* We don't want the template parameter list and constraints. */
buf->writestring(s->Dsymbol::toChars());
}
return true;
}
static void emitAnchor(OutBuffer *buf, Dsymbol *s)
{
buf->writestring("$(DDOC_ANCHOR ");
emitAnchorName(buf, s);
buf->writeByte(')');
}
/******************************* emitComment **********************************/
/** Get leading indentation from 'src' which represents lines of code. */
static size_t getCodeIndent(const char *src)
{
while (src && *src == '\n')
++src; // skip until we find the first non-empty line
size_t codeIndent = 0;
while (src && (*src == ' ' || *src == '\t'))
{
codeIndent++;
src++;
}
return codeIndent;
}
void emitUnittestComment(Scope *sc, Dsymbol *s, size_t ofs)
{
OutBuffer *buf = sc->docbuf;
for (UnitTestDeclaration *utd = s->unittest; utd; utd = utd->unittest)
{
if (utd->protection == PROTprivate || !utd->comment || !utd->fbody)
continue;
// Strip whitespaces to avoid showing empty summary
unsigned char *c = utd->comment;
while (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r') ++c;
OutBuffer codebuf;
codebuf.writestring("$(DDOC_EXAMPLES \n");
size_t o = codebuf.offset;
codebuf.writestring((char *)c);
if (utd->codedoc)
{
size_t i = getCodeIndent(utd->codedoc);
while (i--) codebuf.writeByte(' ');
codebuf.writestring("----\n");
codebuf.writestring(utd->codedoc);
codebuf.writestring("----\n");
highlightText(sc, s, &codebuf, o);
}
codebuf.writestring(")");
buf->insert(buf->offset - ofs, codebuf.data, codebuf.offset);
}
}
/*
* Emit doc comment to documentation file
*/
@@ -505,34 +591,12 @@ void Dsymbol::emitDitto(Scope *sc)
buf->spread(sc->lastoffset, b.offset);
memcpy(buf->data + sc->lastoffset, b.data, b.offset);
sc->lastoffset += b.offset;
}
void emitUnittestComment(Scope *sc, Dsymbol *s, UnitTestDeclaration *test)
{
static char pre[] = "$(D_CODE \n";
OutBuffer *buf = sc->docbuf;
buf->writestring("$(DDOC_SECTION ");
buf->writestring("$(B Example:)");
for (UnitTestDeclaration *utd = test; utd; utd = utd->unittest)
{
if (utd->protection == PROTprivate || !utd->comment || !utd->fbody)
continue;
OutBuffer codebuf;
const char *body = utd->fbody->toChars();
if (strlen(body))
{
codebuf.writestring(pre);
codebuf.writestring(body);
codebuf.writestring(")");
codebuf.writeByte(0);
highlightCode2(sc, s, &codebuf, 0);
buf->writestring(codebuf.toChars());
}
}
buf->writestring(")");
Dsymbol *s = this;
if (!s->unittest && parent)
s = parent->isTemplateDeclaration();
if (s)
emitUnittestComment(sc, s, strlen(ddoc_decl_dd_e));
}
void ScopeDsymbol::emitMemberComments(Scope *sc)
@@ -586,6 +650,7 @@ void emitProtection(OutBuffer *buf, PROT prot)
void Dsymbol::emitComment(Scope *sc) { }
void InvariantDeclaration::emitComment(Scope *sc) { }
void UnitTestDeclaration::emitComment(Scope *sc) { }
#if DMDV2
void PostBlitDeclaration::emitComment(Scope *sc) { }
#endif
@@ -650,8 +715,10 @@ void AggregateDeclaration::emitComment(Scope *sc)
dc->pmacrotable = &sc->module->macrotable;
buf->writestring(ddoc_decl_s);
toDocBuffer(buf, sc);
sc->lastoffset = buf->offset;
size_t o = buf->offset;
toDocBuffer(buf, sc);
highlightCode(sc, this, buf, o);
sc->lastoffset = buf->offset;
buf->writestring(ddoc_decl_e);
buf->writestring(ddoc_decl_dd_s);
@@ -747,7 +814,9 @@ void EnumDeclaration::emitComment(Scope *sc)
dc->pmacrotable = &sc->module->macrotable;
buf->writestring(ddoc_decl_s);
size_t o = buf->offset;
toDocBuffer(buf, sc);
highlightCode(sc, this, buf, o);
sc->lastoffset = buf->offset;
buf->writestring(ddoc_decl_e);
@@ -767,7 +836,6 @@ void EnumMember::emitComment(Scope *sc)
OutBuffer *buf = sc->docbuf;
DocComment *dc = DocComment::parse(sc, this, comment);
size_t o;
if (!dc)
{
@@ -777,7 +845,7 @@ void EnumMember::emitComment(Scope *sc)
dc->pmacrotable = &sc->module->macrotable;
buf->writestring(ddoc_decl_s);
o = buf->offset;
size_t o = buf->offset;
toDocBuffer(buf, sc);
highlightCode(sc, this, buf, o);
sc->lastoffset = buf->offset;
@@ -788,42 +856,6 @@ void EnumMember::emitComment(Scope *sc)
buf->writestring(ddoc_decl_dd_e);
}
static bool emitAnchorName(OutBuffer *buf, Dsymbol *s)
{
if (!s || s->isPackage() || s->isModule())
return false;
TemplateDeclaration *td;
bool dot;
// Add parent names first
dot = emitAnchorName(buf, s->parent);
// Eponymous template members can share the parent anchor name
if (s->parent && (td = s->parent->isTemplateDeclaration()) != NULL &&
td->onemember == s)
return dot;
if (dot)
buf->writeByte('.');
// Use "this" not "__ctor"
if (s->isCtorDeclaration() || ((td = s->isTemplateDeclaration()) != NULL &&
td->onemember && td->onemember->isCtorDeclaration()))
buf->writestring("this");
else
{
/* We just want the identifier, not overloads like TemplateDeclaration::toChars.
* We don't want the template parameter list and constraints. */
buf->writestring(s->Dsymbol::toChars());
}
return true;
}
static void emitAnchor(OutBuffer *buf, Dsymbol *s)
{
buf->writestring("$(DDOC_ANCHOR ");
emitAnchorName(buf, s);
buf->writeByte(')');
}
/******************************* toDocBuffer **********************************/
void Dsymbol::toDocBuffer(OutBuffer *buf, Scope *sc)
@@ -867,6 +899,9 @@ void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclarati
//printf("declarationToDocBuffer() %s, originalType = %s, td = %s\n", decl->toChars(), decl->originalType ? decl->originalType->toChars() : "--", td ? td->toChars() : "--");
if (decl->ident)
{
if (decl->isDeprecated())
buf->writestring("$(DEPRECATED ");
prefix(buf, decl);
if (decl->type)
@@ -883,6 +918,10 @@ void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclarati
}
else
buf->writestring(decl->ident->toChars());
if (decl->isDeprecated())
buf->writestring(")");
buf->writestring(";\n");
}
}
@@ -901,7 +940,7 @@ void AliasDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
buf->writestring("deprecated ");
emitProtection(buf, protection);
buf->writestring("alias ");
buf->printf("alias %s = ", toChars());
if (Dsymbol *s = aliassym) // ident alias
{
@@ -923,8 +962,6 @@ void AliasDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
}
}
buf->writestring(" ");
buf->writestring(toChars());
buf->writestring(";\n");
}
}
@@ -1033,11 +1070,10 @@ void AggregateDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
if (ident)
{
emitAnchor(buf, this);
#if 0
emitProtection(buf, protection);
#endif
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
buf->printf("%s %s", kind(), toChars());
buf->writestring(";\n");
}
}
@@ -1061,8 +1097,7 @@ void StructDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
}
else
{
emitAnchor(buf, this);
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
buf->printf("%s %s", kind(), toChars());
}
buf->writestring(";\n");
}
@@ -1087,10 +1122,9 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
}
else
{
emitAnchor(buf, this);
if (isAbstract())
buf->writestring("abstract ");
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
buf->printf("%s %s", kind(), toChars());
}
int any = 0;
for (size_t i = 0; i < baseclasses->dim; i++)
@@ -1127,8 +1161,7 @@ void EnumDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc)
{
if (ident)
{
emitAnchor(buf, this);
buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars());
buf->printf("%s %s", kind(), toChars());
buf->writestring(";\n");
}
}
@@ -1195,6 +1228,7 @@ void DocComment::parseSections(unsigned char *comment)
p = comment;
while (*p)
{
unsigned char *pstart0 = p;
p = skipwhitespace(p);
pstart = p;
pend = p;
@@ -1210,6 +1244,11 @@ void DocComment::parseSections(unsigned char *comment)
// Check for start/end of a code section
if (*p == '-')
{
if (!inCode)
{ // restore leading indentation
while (pstart0 < pstart && isIndentWS(pstart-1)) --pstart;
}
int numdash = 0;
while (*p == '-')
{
@@ -1298,7 +1337,7 @@ void DocComment::parseSections(unsigned char *comment)
void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
{
//printf("DocComment::writeSections()\n");
if (sections.dim)
if (sections.dim || s->unittest)
{
buf->writestring("$(DDOC_SECTIONS \n");
for (size_t i = 0; i < sections.dim; i++)
@@ -1320,7 +1359,7 @@ void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf)
}
}
if (s->unittest)
emitUnittestComment(sc, s, s->unittest);
emitUnittestComment(sc, s, 0);
buf->writestring(")\n");
}
else
@@ -1911,6 +1950,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
int inCode = 0;
//int inComment = 0; // in <!-- ... --> comment
size_t iCodeStart; // start of code section
size_t codeIndent = 0;
size_t iLineStart = offset;
@@ -2083,6 +2123,30 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
codebuf.write(buf->data + iCodeStart, i - iCodeStart);
codebuf.writeByte(0);
// Remove leading indentations from all lines
bool lineStart = true;
unsigned char *endp = codebuf.data + codebuf.offset;
for (unsigned char *p = codebuf.data; p < endp; )
{
if (lineStart)
{
size_t j = codeIndent;
unsigned char *q = p;
while (j-- > 0 && q < endp && isIndentWS(q))
++q;
codebuf.remove(p - codebuf.data, q - p);
assert(codebuf.data <= p);
assert(p < codebuf.data + codebuf.offset);
lineStart = false;
endp = codebuf.data + codebuf.offset; // update
continue;
}
if (*p == '\n')
lineStart = true;
++p;
}
highlightCode2(sc, s, &codebuf, 0);
buf->remove(iCodeStart, i - iCodeStart);
i = buf->insert(iCodeStart, codebuf.data, codebuf.offset);
@@ -2093,6 +2157,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
{ static char pre[] = "$(D_CODE \n";
inCode = 1;
codeIndent = istart - iLineStart; // save indent count
i = buf->insert(i, pre, sizeof(pre) - 1);
iCodeStart = i;
i--; // place i on >
@@ -2238,6 +2303,9 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
unsigned char *lastp = buf->data;
const char *highlight;
if (s->isModule() && ((Module *)s)->isDocFile)
sid = "";
//printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data);
res.reserve(buf->offset);
while (1)
@@ -2362,6 +2430,15 @@ int isIdTail(unsigned char *p)
return 0;
}
/****************************************
* Determine if p points to the indentation space.
*/
int isIndentWS(unsigned char *p)
{
return (*p == ' ') || (*p == '\t');
}
/*****************************************
* Return number of bytes in UTF character.
*/
+35 -26
View File
@@ -37,22 +37,24 @@
#include "../gen/pragma.h"
#endif
const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};
/****************************** Dsymbol ******************************/
Dsymbol::Dsymbol()
{
//printf("Dsymbol::Dsymbol(%p)\n", this);
this->ident = NULL;
this->c_ident = NULL;
this->parent = NULL;
#if IN_DMD
this->csym = NULL;
this->isym = NULL;
#endif
this->loc = 0;
this->loc = Loc();
this->comment = NULL;
this->scope = NULL;
this->errors = false;
this->depmsg = NULL;
this->userAttributes = NULL;
this->unittest = NULL;
#if IN_LLVM
@@ -64,13 +66,12 @@ Dsymbol::Dsymbol(Identifier *ident)
{
//printf("Dsymbol::Dsymbol(%p, ident)\n", this);
this->ident = ident;
this->c_ident = NULL;
this->parent = NULL;
#if IN_DMD
this->csym = NULL;
this->isym = NULL;
#endif
this->loc = 0;
this->loc = Loc();
this->comment = NULL;
this->scope = NULL;
this->errors = false;
@@ -414,7 +415,7 @@ void *symbol_search_fp(void *arg, const char *seed)
Dsymbol *s = (Dsymbol *)arg;
Module::clearCache();
return s->search(0, id, 4|2);
return s->search(Loc(), id, 4|2);
}
Dsymbol *Dsymbol::search_correct(Identifier *ident)
@@ -432,7 +433,7 @@ Dsymbol *Dsymbol::search_correct(Identifier *ident)
* symbol found, NULL if not
*/
Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Object *id)
{
//printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
Dsymbol *s = toAlias();
@@ -441,7 +442,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
switch (id->dyncast())
{
case DYNCAST_IDENTIFIER:
sm = s->search(loc, id, 0);
sm = s->search(loc, (Identifier *)id, 0);
break;
case DYNCAST_DSYMBOL:
@@ -449,7 +450,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
//printf("\ttemplate instance id\n");
Dsymbol *st = (Dsymbol *)id;
TemplateInstance *ti = st->isTemplateInstance();
id = ti->name;
Identifier *id = ti->name;
sm = s->search(loc, id, 0);
if (!sm)
{
@@ -546,9 +547,9 @@ int Dsymbol::isImportedSymbol()
return FALSE;
}
int Dsymbol::isDeprecated()
bool Dsymbol::isDeprecated()
{
return FALSE;
return false;
}
#if DMDV2
@@ -606,7 +607,7 @@ int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
s2 = sd->symtab->lookup(ident);
if (!s2->overloadInsert(this))
{
sd->multiplyDefined(0, this, s2);
sd->multiplyDefined(Loc(), this, s2);
}
}
if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
@@ -741,7 +742,7 @@ Module *Dsymbol::getAccessModule()
if (m)
return m;
TemplateInstance *ti = s->isTemplateInstance();
if (ti && ti->isnested)
if (ti && ti->enclosing)
/* Because of local template instantiation, the parent isn't where the access
* rights come from - it's the template declaration
*/
@@ -807,8 +808,8 @@ void Dsymbol::addComment(unsigned char *comment)
/********************************* OverloadSet ****************************/
#if DMDV2
OverloadSet::OverloadSet()
: Dsymbol()
OverloadSet::OverloadSet(Identifier *ident)
: Dsymbol(ident)
{
}
@@ -917,12 +918,20 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
)
)
{
/* Bugzilla 8668:
* Public selective import adds AliasDeclaration in module.
* To make an overload set, resolve aliases in here and
* get actual overload roots which accessible via s and s2.
*/
s = s->toAlias();
s2 = s2->toAlias();
/* If both s2 and s are overloadable (though we only
* need to check s once)
*/
if (s2->isOverloadable() && (a || s->isOverloadable()))
{ if (!a)
a = new OverloadSet();
a = new OverloadSet(s->ident);
/* Don't add to a[] if s2 is alias of previous sym
*/
for (size_t j = 0; j < a->a.dim; j++)
@@ -1067,7 +1076,7 @@ Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
return sprev;
}
}
multiplyDefined(0, s, sprev);
multiplyDefined(Loc(), s, sprev);
return sprev;
}
@@ -1218,7 +1227,7 @@ FuncDeclaration *ScopeDsymbol::findGetMembers()
Type *tret = NULL;
tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
tfgetmembers = (TypeFunction *)tfgetmembers->semantic(Loc(), &sc);
}
if (fdx)
fdx = fdx->overloadExactMatch(tfgetmembers);
@@ -1288,8 +1297,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
{ /* $ gives the number of elements in the tuple
*/
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t);
v->init = new ExpInitializer(Loc(), e);
v->storage_class |= STCstatic | STCconst;
v->semantic(sc);
return v;
@@ -1299,8 +1308,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
{ /* $ gives the number of type entries in the type tuple
*/
VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
v->init = new ExpInitializer(0, e);
Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t);
v->init = new ExpInitializer(Loc(), e);
v->storage_class |= STCstatic | STCconst;
v->semantic(sc);
return v;
@@ -1364,8 +1373,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
{ /* It is for an expression tuple, so the
* length will be a const.
*/
Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(0, e));
Expression *e = new IntegerExp(Loc(), ((TupleExp *)ce)->exps->dim, Type::tsize_t);
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(Loc(), e));
v->storage_class |= STCstatic | STCconst;
}
else if (ce->type && (t = ce->type->toBasetype()) != NULL &&
@@ -1427,7 +1436,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
}
Objects *tdargs = new Objects();
Expression *edim = new IntegerExp(0, dim, Type::tsize_t);
Expression *edim = new IntegerExp(Loc(), dim, Type::tsize_t);
edim = edim->semantic(sc);
tdargs->push(edim);
@@ -1457,7 +1466,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
t = e->type->toBasetype();
if (t && t->ty == Tfunction)
e = new CallExp(e->loc, e);
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, e));
v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e));
}
else
{ /* For arrays, $ will either be a compile-time constant
@@ -1465,7 +1474,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
* or a variable (in which case an expression is created in
* toir.c).
*/
VoidInitializer *e = new VoidInitializer(0);
VoidInitializer *e = new VoidInitializer(Loc());
e->type = Type::tsize_t;
v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e);
v->storage_class |= STCctfe; // it's never a true static variable
+7 -9
View File
@@ -76,7 +76,7 @@ struct EnumMember;
struct ScopeDsymbol;
struct WithScopeSymbol;
struct ArrayScopeSymbol;
struct StaticStructInitDeclaration;
struct SymbolDeclaration;
struct Expression;
struct DeleteDeclaration;
struct HdrGenState;
@@ -118,7 +118,7 @@ enum PROT
};
// this is used for printing the protection in json, traits, docs, etc.
static const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};
extern const char* Pprotectionnames[];
/* State of symbol in winding its way through the passes of the compiler
*/
@@ -138,7 +138,6 @@ typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
struct Dsymbol : Object
{
Identifier *ident;
Identifier *c_ident;
Dsymbol *parent;
#if IN_DMD
Symbol *csym; // symbol for code generator
@@ -190,9 +189,8 @@ struct Dsymbol : Object
virtual void inlineScan();
virtual Dsymbol *search(Loc loc, Identifier *ident, int flags);
Dsymbol *search_correct(Identifier *id);
Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id);
Dsymbol *searchX(Loc loc, Scope *sc, Object *id);
virtual int overloadInsert(Dsymbol *s);
char *toHChars();
virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual void toDocBuffer(OutBuffer *buf, Scope *sc);
@@ -207,7 +205,7 @@ struct Dsymbol : Object
ClassDeclaration *isClassMember(); // are we a member of a class?
virtual int isExport(); // is Dsymbol exported?
virtual int isImportedSymbol(); // is Dsymbol imported?
virtual int isDeprecated(); // is Dsymbol deprecated?
virtual bool isDeprecated(); // is Dsymbol deprecated?
#if DMDV2
virtual int isOverloadable();
virtual int hasOverloads();
@@ -215,7 +213,7 @@ struct Dsymbol : Object
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 char *mangle(bool isv = false);
virtual const char *mangle(bool isv = false);
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
@@ -281,7 +279,7 @@ struct Dsymbol : Object
virtual Import *isImport() { return NULL; }
virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; }
virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; }
virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; }
virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
#if IN_LLVM
@@ -369,7 +367,7 @@ struct OverloadSet : Dsymbol
{
Dsymbols a; // array of Dsymbols
OverloadSet();
OverloadSet(Identifier *ident);
void push(Dsymbol *s);
OverloadSet *isOverloadSet() { return this; }
const char *kind();
+2263 -2263
View File
File diff suppressed because it is too large Load Diff
+106 -27
View File
@@ -18,6 +18,7 @@
#include "expression.h"
#include "module.h"
#include "declaration.h"
#include "init.h"
/********************************* EnumDeclaration ****************************/
@@ -33,7 +34,7 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
#if IN_DMD
sinit = NULL;
#endif
isdeprecated = 0;
isdeprecated = false;
isdone = 0;
#if IN_DMD
objFileDone = 0;
@@ -56,6 +57,14 @@ Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
else
ed = new EnumDeclaration(loc, ident, t);
ScopeDsymbol::syntaxCopy(ed);
if (isAnonymous())
{
for (size_t i = 0; i < members->dim; i++)
{
EnumMember *em = (*members)[i]->isEnumMember();
em->ed = ed;
}
}
return ed;
}
@@ -66,6 +75,23 @@ void EnumDeclaration::setScope(Scope *sc)
ScopeDsymbol::setScope(sc);
}
int EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
if (!isAnonymous())
return ScopeDsymbol::addMember(sc, sd, memnum);
/* Anonymous enum members get added to enclosing scope.
*/
for (size_t i = 0; i < members->dim; i++)
{
EnumMember *em = (*members)[i]->isEnumMember();
em->ed = this;
//printf("add %s\n", em->toChars());
em->addMember(sc, sd, 1);
}
return 1;
}
void EnumDeclaration::semantic0(Scope *sc)
{
/* This function is a hack to get around a significant problem.
@@ -105,7 +131,7 @@ void EnumDeclaration::semantic(Scope *sc)
//printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
//printf("EnumDeclaration::semantic() %s\n", toChars());
if (!members) // enum ident;
if (!members && !memtype) // enum ident;
return;
if (!memtype && !isAnonymous())
@@ -130,7 +156,7 @@ void EnumDeclaration::semantic(Scope *sc)
unsigned dprogress_save = Module::dprogress;
if (sc->stc & STCdeprecated)
isdeprecated = 1;
isdeprecated = true;
userAttributes = sc->userAttributes;
parent = sc->parent;
@@ -161,6 +187,11 @@ void EnumDeclaration::semantic(Scope *sc)
return;
}
}
if (memtype->ty == Tvoid)
{
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());
@@ -170,6 +201,10 @@ void EnumDeclaration::semantic(Scope *sc)
}
isdone = 1;
if (!members) // enum ident : memtype;
return;
Module::dprogress++;
type = type->semantic(loc, sc);
@@ -181,6 +216,26 @@ void EnumDeclaration::semantic(Scope *sc)
}
if (members->dim == 0)
error("enum %s must have at least one member", toChars());
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;
for (size_t i = 0; i < members->dim; i++)
@@ -202,7 +257,7 @@ void EnumDeclaration::semantic(Scope *sc)
if (e)
{
assert(e->dyncast() == DYNCAST_EXPRESSION);
e = e->semantic(sce);
e = e->ctfeSemantic(sce);
e = e->ctfeInterpret();
if (memtype)
{
@@ -236,13 +291,20 @@ void EnumDeclaration::semantic(Scope *sc)
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(0, Id::max);
emax = emax->semantic(sce);
emax = t->getProperty(Loc(), Id::max, 0);
emax = emax->ctfeSemantic(sce);
emax = emax->ctfeInterpret();
}
@@ -250,14 +312,14 @@ void EnumDeclaration::semantic(Scope *sc)
// But first check that (elast != t.max)
assert(elast);
e = new EqualExp(TOKequal, em->loc, elast, emax);
e = e->semantic(sce);
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->semantic(sce);
e = e->ctfeSemantic(sce);
e = e->castTo(sce, elast->type);
e = e->ctfeInterpret();
@@ -265,7 +327,7 @@ void EnumDeclaration::semantic(Scope *sc)
{
// Check that e != elast (not always true for floats)
Expression *etest = new EqualExp(TOKequal, em->loc, e, elast);
etest = etest->semantic(sce);
etest = etest->ctfeSemantic(sce);
etest = etest->ctfeInterpret();
if (etest->toInteger())
error("enum member %s has inexact value, due to loss of precision", em->toChars());
@@ -275,29 +337,22 @@ void EnumDeclaration::semantic(Scope *sc)
em->value = e;
// Add to symbol table only after evaluating 'value'
if (isAnonymous())
if (isAnonymous() && !sc->func)
{
/* Anonymous enum members get added to enclosing scope.
*/
for (Scope *sct = sce; sct; sct = sct->enclosing)
{
if (sct->scopesym)
{
if (!sct->scopesym->symtab)
sct->scopesym->symtab = new DsymbolTable();
em->addMember(sce, sct->scopesym, 1);
break;
}
}
// already inserted to enclosing scope in addMember
assert(em->ed);
}
else
em->addMember(sc, this, 1);
{
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 (!isAnonymous())
if (!isAnonymous() && memtype != Type::terror)
{
if (first)
{ defaultval = e;
@@ -315,13 +370,13 @@ void EnumDeclaration::semantic(Scope *sc)
// Compute if(e < minval)
ec = new CmpExp(TOKlt, em->loc, e, minval);
ec = ec->semantic(sce);
ec = ec->ctfeSemantic(sce);
ec = ec->ctfeInterpret();
if (ec->toInteger())
minval = e;
ec = new CmpExp(TOKgt, em->loc, e, maxval);
ec = ec->semantic(sce);
ec = ec->ctfeSemantic(sce);
ec = ec->ctfeInterpret();
if (ec->toInteger())
maxval = e;
@@ -390,7 +445,7 @@ const char *EnumDeclaration::kind()
return "enum";
}
int EnumDeclaration::isDeprecated()
bool EnumDeclaration::isDeprecated()
{
return isdeprecated;
}
@@ -417,9 +472,11 @@ Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags)
EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type)
: Dsymbol(id)
{
this->ed = NULL;
this->value = value;
this->type = type;
this->loc = loc;
this->vd = NULL;
}
Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
@@ -462,4 +519,26 @@ const char *EnumMember::kind()
return "enum member";
}
void EnumMember::semantic(Scope *sc)
{
assert(ed);
if (this->vd) return;
ed->semantic(sc);
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 *EnumMember::getVarExp(Loc loc, Scope *sc)
{
semantic(sc);
assert(vd);
Expression *e = new VarExp(loc, vd);
return e->semantic(sc);
}
+8 -6
View File
@@ -22,7 +22,7 @@ struct Identifier;
struct Type;
struct Expression;
struct HdrGenState;
struct VarDeclaration;
struct EnumDeclaration : ScopeDsymbol
{ /* enum ident : memtype { ... }
@@ -40,15 +40,13 @@ struct EnumDeclaration : ScopeDsymbol
Expression *minval;
Expression *defaultval; // default initializer
#endif
int isdeprecated;
bool isdeprecated;
int isdone; // 0: not done
// 1: semantic() successfully completed
#ifdef IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
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);
@@ -59,7 +57,7 @@ struct EnumDeclaration : ScopeDsymbol
#if DMDV2
Dsymbol *search(Loc, Identifier *ident, int flags);
#endif
int isDeprecated(); // is Dsymbol deprecated?
bool isDeprecated(); // is Dsymbol deprecated?
void emitComment(Scope *sc);
void toJson(JsonOut *json);
@@ -85,13 +83,17 @@ struct EnumDeclaration : ScopeDsymbol
struct EnumMember : Dsymbol
{
EnumDeclaration *ed;
Expression *value;
Type *type;
VarDeclaration *vd;
EnumMember(Loc loc, Identifier *id, Expression *value, Type *type);
Dsymbol *syntaxCopy(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
void semantic(Scope *sc);
Expression *getVarExp(Loc loc, Scope *sc);
void emitComment(Scope *sc);
void toJson(JsonOut *json);
+1472 -824
View File
File diff suppressed because it is too large Load Diff
+126 -79
View File
@@ -52,7 +52,7 @@ struct Initializer;
struct StringExp;
#if IN_LLVM
struct AssignExp;
struct StaticStructInitDeclaration;
struct SymbolDeclaration;
#endif
enum TOK;
@@ -102,7 +102,7 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
#if DMDV2
Expression *resolveAliasThis(Scope *sc, Expression *e);
Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope);
int checkPostblit(Loc loc, Type *t);
bool checkPostblit(Loc loc, Type *t);
#endif
struct ArrayExp *resolveOpDollar(Scope *sc, struct ArrayExp *ae);
struct SliceExp *resolveOpDollar(Scope *sc, struct SliceExp *se);
@@ -118,6 +118,13 @@ enum CtfeGoal
ctfeNeedNothing // The return value is not required
};
#define WANTflags 1
#define WANTvalue 2
// A compile-time result is required. Give an error if not possible
#define WANTinterpret 4
// Same as WANTvalue, but also expand variables as far as possible
#define WANTexpand 8
struct Expression : Object
{
Loc loc; // file location
@@ -127,11 +134,13 @@ struct Expression : Object
unsigned char parens; // if this is a parenthesized expression
Expression(Loc loc, enum TOK op, int size);
static void init();
Expression *copy();
virtual Expression *syntaxCopy();
virtual int apply(apply_fp_t fp, void *param);
virtual Expression *semantic(Scope *sc);
Expression *trySemantic(Scope *sc);
Expression *ctfeSemantic(Scope *sc);
int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression()
@@ -161,7 +170,7 @@ struct Expression : Object
virtual MATCH implicitConvTo(Type *t);
virtual IntRange getIntRange();
virtual Expression *castTo(Scope *sc, Type *t);
virtual Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
virtual Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
virtual void checkEscape();
virtual void checkEscapeRef();
virtual Expression *resolveLoc(Loc loc, Scope *sc);
@@ -185,12 +194,6 @@ struct Expression : Object
Expression *toDelegate(Scope *sc, Type *t);
virtual Expression *optimize(int result, bool keepLvalue = false);
#define WANTflags 1
#define WANTvalue 2
// A compile-time result is required. Give an error if not possible
#define WANTinterpret 4
// Same as WANTvalue, but also expand variables as far as possible
#define WANTexpand 8
// Entry point for CTFE.
// A compile-time result is required. Give an error if not possible
@@ -329,7 +332,6 @@ struct ComplexExp : Expression
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
OutBuffer hexp;
#if IN_DMD
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
@@ -345,7 +347,6 @@ struct IdentifierExp : Expression
Declaration *var;
IdentifierExp(Loc loc, Identifier *ident);
IdentifierExp(Loc loc, Declaration *var);
Expression *semantic(Scope *sc);
char *toChars();
void dump(int indent);
@@ -476,8 +477,17 @@ struct StringExp : Expression
struct TupleExp : Expression
{
Expression *e0; // side-effect part
/* Tuple-field access may need to take out its side effect part.
* For example:
* foo().tupleof
* is rewritten as:
* (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...))
* The declaration of temporary variable __tup will be stored in TupleExp::e0.
*/
Expressions *exps;
TupleExp(Loc loc, Expression *e0, Expressions *exps);
TupleExp(Loc loc, Expressions *exps);
TupleExp(Loc loc, TupleDeclaration *tup);
Expression *syntaxCopy();
@@ -513,6 +523,11 @@ struct ArrayLiteralExp : Expression
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int isBool(int result);
#if IN_LLVM
DValue* toElem(IRState* irs);
#else
elem *toElem(IRState *irs);
#endif
StringExp *toString();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
@@ -520,18 +535,15 @@ struct ArrayLiteralExp : Expression
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
#if IN_LLVM
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
#if IN_DMD
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
#elif IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
#endif
};
struct AssocArrayLiteralExp : Expression
@@ -555,7 +567,7 @@ struct AssocArrayLiteralExp : Expression
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -565,6 +577,17 @@ struct AssocArrayLiteralExp : Expression
#endif
};
// scrubReturnValue is running
#define stageScrub 0x1
// hasNonConstPointers is running
#define stageSearchPointers 0x2
// optimize is running
#define stageOptimize 0x4
// apply is running
#define stageApply 0x8
//inlineScan is running
#define stageInlineScan 0x10
struct StructLiteralExp : Expression
{
StructDeclaration *sd; // which aggregate this is for
@@ -581,8 +604,19 @@ struct StructLiteralExp : Expression
bool ownedByCtfe; // true = created in CTFE
int ctorinit;
StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL);
StructLiteralExp *origin; // pointer to the origin instance of the expression.
// once a new expression is created, origin is set to 'this'.
// anytime when an expression copy is created, 'origin' pointer is set to
// 'origin' pointer value of the original expression.
StructLiteralExp *inlinecopy; // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
int stageflags; // anytime when recursive function is calling, 'stageflags' marks with bit flag of
// current stage and unmarks before return from this function.
// 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
// (with infinite recursion) of this expression.
StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL);
int equals(Object *o);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
@@ -592,35 +626,30 @@ struct StructLiteralExp : Expression
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
#if IN_DMD
elem *toElem(IRState *irs);
dt_t **toDt(dt_t **pdt);
#elif IN_LLVM
#if IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
llvm::StructType *constType;
/// Set if this is really the result of a struct .init access and should be
/// resolved codegen'd as an access to the given StaticStructInitDeclaration.
/// resolved codegen'd as an access to the given SymbolDeclaration.
// LDC_FIXME: Figure out whether this, i.e. imitating the DMD behavior, is
// really the best way to fix the nested struct constant folding issue.
StaticStructInitDeclaration *sinit;
SymbolDeclaration *sinit;
#else
dt_t **toDt(dt_t **pdt);
Symbol *toSymbol();
#endif
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident);
#if IN_DMD
#endif
#if IN_LLVM
DValue* toElem(IRState* irs);
#endif
struct DotIdExp;
DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident);
struct TypeExp : Expression
{
@@ -659,10 +688,13 @@ struct ScopeExp : Expression
struct TemplateExp : Expression
{
TemplateDeclaration *td;
FuncDeclaration *fd;
TemplateExp(Loc loc, TemplateDeclaration *td);
TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd = NULL);
int rvalue();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
struct NewExp : Expression
@@ -743,6 +775,7 @@ struct SymOffExp : SymbolExp
SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads = 0);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -800,7 +833,7 @@ struct OverExp : Expression
{
OverloadSet *vars;
OverExp(OverloadSet *s);
OverExp(Loc loc, OverloadSet *s);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
};
@@ -822,7 +855,7 @@ struct FuncExp : Expression
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
@@ -926,6 +959,7 @@ struct IsExp : Expression
struct UnaExp : Expression
{
Expression *e1;
Type *att1; // Save alias this type to detect recursion
UnaExp(Loc loc, enum TOK op, int size, Expression *e1);
Expression *syntaxCopy();
@@ -934,8 +968,7 @@ struct UnaExp : Expression
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result, bool keepLvalue = false);
void dump(int indent);
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *));
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *resolveLoc(Loc loc, Scope *sc);
Expression *doInline(InlineDoState *ids);
@@ -949,6 +982,9 @@ struct BinExp : Expression
Expression *e1;
Expression *e2;
Type *att1; // Save alias this type to detect recursion
Type *att2; // Save alias this type to detect recursion
BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
@@ -963,6 +999,7 @@ struct BinExp : Expression
Expression *incompatibleTypes();
void dump(int indent);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *));
Expression *interpretCompareCommon(InterState *istate, CtfeGoal goal,
@@ -977,6 +1014,7 @@ struct BinExp : Expression
Expression *op_overload(Scope *sc);
Expression *compare_overload(Scope *sc, Identifier *id);
Expression *reorderSettingAAElem(Scope *sc);
#if IN_DMD
elem *toElemBin(IRState *irs, int op);
@@ -993,6 +1031,8 @@ struct BinAssignExp : BinExp
Expression *semantic(Scope *sc);
Expression *arrayOp(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *op_overload(Scope *sc);
int isLvalue();
@@ -1045,7 +1085,8 @@ struct DotIdExp : UnaExp
DotIdExp(Loc loc, Expression *e, Identifier *ident);
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, int flag);
Expression *semanticX(Scope *sc);
Expression *semanticY(Scope *sc, int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int i);
};
@@ -1091,7 +1132,7 @@ struct DotTemplateInstanceExp : UnaExp
Expression *syntaxCopy();
TemplateDeclaration *getTempdecl(Scope *sc);
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, int flag);
Expression *semanticY(Scope *sc, int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
};
@@ -1147,7 +1188,6 @@ struct CallExp : UnaExp
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *resolveUFCS(Scope *sc);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
@@ -1186,6 +1226,8 @@ struct AddrExp : UnaExp
#if IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
@@ -1220,7 +1262,6 @@ struct NegExp : UnaExp
NegExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1251,7 +1292,6 @@ struct ComExp : UnaExp
ComExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1273,7 +1313,6 @@ struct NotExp : UnaExp
NotExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1289,7 +1328,6 @@ struct BoolExp : UnaExp
BoolExp(Loc loc, Expression *e, Type *type);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1344,6 +1382,8 @@ struct CastExp : UnaExp
#if IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
#else
dt_t **toDt(dt_t **pdt);
#endif
};
@@ -1383,6 +1423,9 @@ struct SliceExp : UnaExp
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *toStaticArrayType();
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void dump(int indent);
@@ -1568,7 +1611,6 @@ struct op##AssignExp : BinAssignExp \
{ \
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
S(Expression *semantic(Scope *sc);) \
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
X(Expression *buildArrayLoop(Parameters *fparams);) \
\
@@ -1619,7 +1661,6 @@ struct AddExp : BinExp
AddExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1644,7 +1685,6 @@ struct MinExp : BinExp
MinExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1688,7 +1728,6 @@ struct MulExp : BinExp
MulExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1712,7 +1751,6 @@ struct DivExp : BinExp
DivExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1735,7 +1773,6 @@ struct ModExp : BinExp
ModExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1759,7 +1796,6 @@ struct PowExp : BinExp
PowExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
@@ -1782,7 +1818,6 @@ struct ShlExp : BinExp
ShlExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
IntRange getIntRange();
// For operator overloading
@@ -1803,7 +1838,6 @@ struct ShrExp : BinExp
ShrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
IntRange getIntRange();
// For operator overloading
@@ -1824,7 +1858,6 @@ struct UshrExp : BinExp
UshrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
IntRange getIntRange();
// For operator overloading
@@ -1845,7 +1878,6 @@ struct AndExp : BinExp
AndExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
IntRange getIntRange();
@@ -1869,7 +1901,6 @@ struct OrExp : BinExp
OrExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
MATCH implicitConvTo(Type *t);
@@ -1894,7 +1925,6 @@ struct XorExp : BinExp
XorExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
MATCH implicitConvTo(Type *t);
@@ -1953,7 +1983,6 @@ struct CmpExp : BinExp
CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
// For operator overloading
@@ -2011,7 +2040,6 @@ struct EqualExp : BinExp
EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isBit();
// For operator overloading
@@ -2036,13 +2064,10 @@ struct IdentityExp : BinExp
Expression *semantic(Scope *sc);
int isBit();
Expression *optimize(int result, bool keepLvalue = false);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
#if IN_LLVM
DValue* toElem(IRState* irs);
#else
elem *toElem(IRState *irs);
#endif
};
@@ -2068,7 +2093,7 @@ struct CondExp : BinExp
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -2106,6 +2131,28 @@ struct LineInitExp : DefaultInitExp
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
struct ModuleInitExp : DefaultInitExp
{
ModuleInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
struct FuncInitExp : DefaultInitExp
{
FuncInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
struct PrettyFuncInitExp : DefaultInitExp
{
PrettyFuncInitExp(Loc loc);
Expression *semantic(Scope *sc);
Expression *resolveLoc(Loc loc, Scope *sc);
};
#endif
/****************************************************************/
@@ -2132,11 +2179,11 @@ struct GEPExp : UnaExp
/* Special values used by the interpreter
*/
#define EXP_CANT_INTERPRET ((Expression *)1)
#define EXP_CONTINUE_INTERPRET ((Expression *)2)
#define EXP_BREAK_INTERPRET ((Expression *)3)
#define EXP_GOTO_INTERPRET ((Expression *)4)
#define EXP_VOID_INTERPRET ((Expression *)5)
extern Expression *EXP_CANT_INTERPRET;
extern Expression *EXP_CONTINUE_INTERPRET;
extern Expression *EXP_BREAK_INTERPRET;
extern Expression *EXP_GOTO_INTERPRET;
extern Expression *EXP_VOID_INTERPRET;
Expression *expType(Type *type, Expression *e);
+538 -257
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -51,7 +51,6 @@ const char *Identifier::toHChars2()
if (this == Id::ctor) p = "this";
else if (this == Id::dtor) p = "~this";
else if (this == Id::classInvariant) p = "invariant";
else if (this == Id::unitTest) p = "unittest";
else if (this == Id::dollar) p = "$";
else if (this == Id::withSym) p = "with";
@@ -65,6 +64,8 @@ const char *Identifier::toHChars2()
p = "static this";
else if (memcmp(p, "_staticDtor", 11) == 0)
p = "static ~this";
else if (memcmp(p, "__invariant", 11) == 0)
p = "invariant";
}
}
@@ -73,7 +74,7 @@ const char *Identifier::toHChars2()
void Identifier::print()
{
fprintf(stdmsg, "%s",string);
fprintf(stderr, "%s",string);
}
int Identifier::dyncast()
-1
View File
@@ -36,7 +36,6 @@ struct Identifier : Object
int compare(Object *o);
void print();
char *toChars();
char *toHChars();
const char *toHChars2();
int dyncast();
+5 -1
View File
@@ -108,6 +108,9 @@ Msgtable msgtable[] =
{ "LINE", "__LINE__" },
{ "FILE", "__FILE__" },
{ "MODULE", "__MODULE__" },
{ "FUNCTION", "__FUNCTION__" },
{ "PRETTY_FUNCTION", "__PRETTY_FUNCTION__" },
{ "DATE", "__DATE__" },
{ "TIME", "__TIME__" },
{ "TIMESTAMP", "__TIMESTAMP__" },
@@ -260,10 +263,10 @@ Msgtable msgtable[] =
{ "_ArrayEq" },
// For pragma's
{ "GNU_asm" },
{ "lib" },
{ "msg" },
{ "startaddress" },
{ "mangle" },
#if IN_LLVM
// LDC-specific pragmas.
@@ -353,6 +356,7 @@ Msgtable msgtable[] =
{ "isAssociativeArray" },
{ "isFinalClass" },
{ "isPOD" },
{ "isNested" },
{ "isFloating" },
{ "isIntegral" },
{ "isScalar" },
+28 -8
View File
@@ -381,44 +381,64 @@ int main()
fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
if (i)
fprintf(fp, ",");
fprintf(fp, "{");
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvResult[i][j]);
if (j)
fprintf(fp, ",");
fprintf(fp, "%d",impcnvResult[i][j]);
}
fprintf(fp, "\n");
fprintf(fp, "}\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
if (i)
fprintf(fp, ",");
fprintf(fp, "{");
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvType1[i][j]);
if (j)
fprintf(fp, ",");
fprintf(fp, "%d",impcnvType1[i][j]);
}
fprintf(fp, "\n");
fprintf(fp, "}\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
if (i)
fprintf(fp, ",");
fprintf(fp, "{");
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvType2[i][j]);
if (j)
fprintf(fp, ",");
fprintf(fp, "%d",impcnvType2[i][j]);
}
fprintf(fp, "\n");
fprintf(fp, "}\n");
}
fprintf(fp,"};\n");
fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n");
for (i = 0; i < TMAX; i++)
{
if (i)
fprintf(fp, ",");
fprintf(fp, "{");
for (j = 0; j < TMAX; j++)
{
fprintf(fp, "%d,",impcnvWarn[i][j]);
if (j)
fprintf(fp, ",");
fprintf(fp, "%d",impcnvWarn[i][j]);
}
fprintf(fp, "\n");
fprintf(fp, "}\n");
}
fprintf(fp,"};\n");
+2 -3
View File
@@ -164,7 +164,7 @@ void Import::importAll(Scope *sc)
{
load(sc);
if (mod) // if successfully loaded module
{ mod->importAll(0);
{ mod->importAll(NULL);
if (!isstatic && !aliasId && !names.dim)
{
@@ -189,7 +189,7 @@ void Import::semantic(Scope *sc)
if (!mod)
{ load(sc);
if (mod)
mod->importAll(0);
mod->importAll(NULL);
}
if (mod)
@@ -245,7 +245,6 @@ void Import::semantic(Scope *sc)
if (mod->search(loc, names[i], 0))
{
ad->semantic(sc);
ad->import = NULL; // forward reference resolved
}
else
{
+137 -34
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
@@ -65,15 +65,48 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
}
char *Initializer::toChars()
{ OutBuffer *buf;
{
HdrGenState hgs;
memset(&hgs, 0, sizeof(hgs));
buf = new OutBuffer();
OutBuffer *buf = new OutBuffer();
toCBuffer(buf, &hgs);
return buf->toChars();
}
/********************************** ErrorInitializer ***************************/
ErrorInitializer::ErrorInitializer()
: Initializer(Loc())
{
}
Initializer *ErrorInitializer::syntaxCopy()
{
return this;
}
Initializer *ErrorInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
//printf("ErrorInitializer::semantic(t = %p)\n", t);
return this;
}
Expression *ErrorInitializer::toExpression(Type *t)
{
return new ErrorExp();
}
void ErrorInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writestring("__error__");
}
/********************************** VoidInitializer ***************************/
VoidInitializer::VoidInitializer(Loc loc)
@@ -97,10 +130,10 @@ Initializer *VoidInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInt
}
Expression *VoidInitializer::toExpression()
Expression *VoidInitializer::toExpression(Type *t)
{
error(loc, "void initializer has no value");
return new IntegerExp(0);
return new ErrorExp();
}
@@ -173,9 +206,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
errors = 1;
goto Lerror;
}
size_t nfields = sd->fields.dim;
if (sd->isnested)
nfields--;
size_t nfields = sd->fields.dim - sd->isNested();
for (size_t i = 0; i < field.dim; i++)
{
Identifier *id = field[i];
@@ -233,6 +264,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
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());
@@ -246,7 +279,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
*/
Parameters *arguments = new Parameters;
Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, TOKdelegate, NULL);
fd->fbody = new CompoundStatement(loc, new Statements());
fd->endloc = loc;
Expression *e = new FuncExp(loc, fd);
@@ -261,9 +294,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI
Lerror:
if (errors)
{
field.setDim(0);
value.setDim(0);
vars.setDim(0);
return new ErrorInitializer();
}
return this;
}
@@ -273,7 +304,7 @@ Lerror:
* a struct literal. In the future, the two should be the
* same thing.
*/
Expression *StructInitializer::toExpression()
Expression *StructInitializer::toExpression(Type *t)
{ Expression *e;
size_t offset;
@@ -285,11 +316,7 @@ Expression *StructInitializer::toExpression()
return NULL;
Expressions *elements = new Expressions();
size_t nfields = ad->fields.dim;
#if DMDV2
if (sd->isnested)
nfields--;
#endif
size_t nfields = ad->fields.dim - sd->isNested();
elements->setDim(nfields);
for (size_t i = 0; i < elements->dim; i++)
{
@@ -305,7 +332,7 @@ Expression *StructInitializer::toExpression()
if (!s)
{
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
goto Lno;
goto Lerror;
}
s = s->toAlias();
@@ -315,7 +342,7 @@ Expression *StructInitializer::toExpression()
if (fieldi >= nfields)
{
s->error("is not a per-instance initializable field");
goto Lno;
goto Lerror;
}
if (s == ad->fields[fieldi])
break;
@@ -323,7 +350,7 @@ Expression *StructInitializer::toExpression()
}
else if (fieldi >= nfields)
{ error(loc, "too many initializers for '%s'", ad->toChars());
goto Lno;
goto Lerror;
}
Initializer *iz = value[i];
if (!iz)
@@ -334,7 +361,7 @@ Expression *StructInitializer::toExpression()
if ((*elements)[fieldi])
{ error(loc, "duplicate initializer for field '%s'",
ad->fields[fieldi]->toChars());
goto Lno;
goto Lerror;
}
(*elements)[fieldi] = ex;
++fieldi;
@@ -399,7 +426,7 @@ Expression *StructInitializer::toExpression()
error(loc, "%s cannot have initializers for fields %s and %s in same union",
ad->toChars(),
v1->toChars(), v->toChars());
goto Lno;
goto Lerror;
}
found = j;
}
@@ -407,12 +434,19 @@ Expression *StructInitializer::toExpression()
{
error(loc, "no initializer for union that contains field %s",
vd->toChars());
goto Lno;
goto Lerror;
}
}
i += unionSize;
#endif
}
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (*elements)[i];
if (e && e->op == TOKerror)
return e;
}
e = new StructLiteralExp(loc, sd, elements);
e->type = sd->type;
return e;
@@ -420,6 +454,10 @@ Expression *StructInitializer::toExpression()
Lno:
delete elements;
return NULL;
Lerror:
delete elements;
return new ErrorExp();
}
@@ -430,7 +468,7 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
for (size_t i = 0; i < field.dim; i++)
{
if (i > 0)
buf->writebyte(',');
buf->writestring(", ");
Identifier *id = field[i];
if (id)
{
@@ -488,6 +526,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
{
size_t length;
const unsigned amax = 0x80000000;
bool errors = false;
//printf("ArrayInitializer::semantic(%s)\n", t->toChars());
if (sem) // if semantic() already run
@@ -522,10 +561,12 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
{
Expression *idx = index[i];
if (idx)
{ idx = idx->semantic(sc);
{ idx = idx->ctfeSemantic(sc);
idx = idx->ctfeInterpret();
index[i] = idx;
length = idx->toInteger();
if (idx->op == TOKerror)
errors = true;
}
Initializer *val = value[i];
@@ -533,6 +574,8 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
if (ei && !idx)
ei->expandTuples = 1;
val = val->semantic(sc, t->nextOf(), needInterpret);
if (val->isErrorInitializer())
errors = true;
ei = val->isExpInitializer();
// found a tuple, expand it
@@ -573,6 +616,8 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
goto Lerr;
}
}
if (errors)
goto Lerr;
if ((uinteger_t) dim * t->nextOf()->size() >= amax)
{ error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size()));
@@ -581,7 +626,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn
return this;
Lerr:
return new ExpInitializer(loc, new ErrorExp());
return new ErrorInitializer();
}
/********************************
@@ -589,12 +634,12 @@ Lerr:
* Otherwise return NULL.
*/
Expression *ArrayInitializer::toExpression()
{ Expressions *elements;
Expression *ArrayInitializer::toExpression(Type *tx)
{
//printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
//static int i; if (++i == 2) halt();
Expressions *elements;
size_t edim;
Type *t = NULL;
if (type)
@@ -670,6 +715,12 @@ Expression *ArrayInitializer::toExpression()
}
}
for (size_t i = 0; i < edim; i++)
{ Expression *e = (*elements)[i];
if (e->op == TOKerror)
return e;
}
Expression *e = new ArrayLiteralExp(loc, elements);
e->type = type;
return e;
@@ -785,7 +836,7 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
for (size_t i = 0; i < index.dim; i++)
{
if (i > 0)
buf->writebyte(',');
buf->writestring(", ");
Expression *ex = index[i];
if (ex)
{
@@ -845,6 +896,27 @@ bool hasNonConstPointers(Expression *e)
return arrayHasNonConstPointers(ae->keys);
return false;
}
if(e->op == TOKaddress)
{
AddrExp *ae = (AddrExp *)e;
if (ae->e1->op == TOKstructliteral)
{
StructLiteralExp *se = (StructLiteralExp *)ae->e1;
if (!(se->stageflags & stageSearchPointers))
{
int old = se->stageflags;
se->stageflags |= stageSearchPointers;
bool ret = arrayHasNonConstPointers(se->elements);
se->stageflags = old;
return ret;
}
else
{
return false;
}
}
return true;
}
if (e->type->ty== Tpointer && e->type->nextOf()->ty != Tfunction)
{
if (e->op == TOKsymoff) // address of a global is OK
@@ -873,7 +945,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());
exp = exp->semantic(sc);
if (needInterpret)
exp = exp->ctfeSemantic(sc);
else
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
if (exp->op == TOKerror)
return this;
@@ -887,13 +962,16 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
return this; // Failed, suppress duplicate error messages
if (exp->op == TOKtype)
{
exp->error("initializer must be an expression, not '%s'", exp->toChars());
return new ErrorInitializer();
}
// Make sure all pointers are constants
if (needInterpret && hasNonConstPointers(exp))
{
exp->error("cannot use non-constant CTFE pointer in an initializer '%s'", exp->toChars());
return this;
return new ErrorInitializer();
}
Type *tb = t->toBasetype();
@@ -949,6 +1027,9 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte
exp->implicitConvTo(tb->nextOf())
)
{
/* If the variable is not actually used in compile time, array creation is
* redundant. So delay it until invocation of toExpression() or toDt().
*/
t = tb->nextOf();
}
@@ -983,7 +1064,10 @@ Type *ExpInitializer::inferType(Scope *sc)
if (exp->op == TOKsymoff)
{ 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
@@ -992,7 +1076,10 @@ Type *ExpInitializer::inferType(Scope *sc)
if (se->hasOverloads &&
se->func->isFuncDeclaration() &&
!se->func->isFuncDeclaration()->isUnique())
{
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
return Type::terror;
}
}
Type *t = exp->type;
@@ -1001,8 +1088,24 @@ Type *ExpInitializer::inferType(Scope *sc)
return t;
}
Expression *ExpInitializer::toExpression()
Expression *ExpInitializer::toExpression(Type *t)
{
if (t)
{
Type *tb = t->toBasetype();
if (tb->ty == Tsarray && exp->implicitConvTo(tb->nextOf()))
{
TypeSArray *tsa = (TypeSArray *)tb;
size_t d = tsa->dim->toInteger();
Expressions *elements = new Expressions();
elements->setDim(d);
for (size_t i = 0; i < d; i++)
(*elements)[i] = exp;
ArrayLiteralExp *ae = new ArrayLiteralExp(exp->loc, elements);
ae->type = t;
exp = ae;
}
}
return exp;
}
+22 -9
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
@@ -22,6 +22,7 @@ struct Scope;
struct Type;
struct dt_t;
struct AggregateDeclaration;
struct ErrorInitializer;
struct VoidInitializer;
struct StructInitializer;
struct ArrayInitializer;
@@ -45,7 +46,7 @@ struct Initializer : Object
// needInterpret is INITinterpret if must be a manifest constant, 0 if not.
virtual Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
virtual Type *inferType(Scope *sc);
virtual Expression *toExpression() = 0;
virtual Expression *toExpression(Type *t = NULL) = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
char *toChars();
@@ -55,10 +56,11 @@ struct Initializer : Object
virtual dt_t *toDt();
#endif
virtual VoidInitializer *isVoidInitializer() { return NULL; }
virtual ErrorInitializer *isErrorInitializer() { return NULL; }
virtual VoidInitializer *isVoidInitializer() { return NULL; }
virtual StructInitializer *isStructInitializer() { return NULL; }
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
virtual ExpInitializer *isExpInitializer() { return NULL; }
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
virtual ExpInitializer *isExpInitializer() { return NULL; }
};
struct VoidInitializer : Initializer
@@ -68,7 +70,7 @@ struct VoidInitializer : Initializer
VoidInitializer(Loc loc);
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Expression *toExpression();
Expression *toExpression(Type *t = NULL);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
@@ -78,6 +80,17 @@ struct VoidInitializer : Initializer
virtual VoidInitializer *isVoidInitializer() { return this; }
};
struct ErrorInitializer : Initializer
{
ErrorInitializer();
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Expression *toExpression(Type *t = NULL);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
virtual ErrorInitializer *isErrorInitializer() { return this; }
};
struct StructInitializer : Initializer
{
Identifiers field; // of Identifier *'s
@@ -90,7 +103,7 @@ struct StructInitializer : Initializer
Initializer *syntaxCopy();
void addInit(Identifier *field, Initializer *value);
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Expression *toExpression();
Expression *toExpression(Type *t = NULL);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
@@ -117,7 +130,7 @@ struct ArrayInitializer : Initializer
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
int isAssociativeArray();
Type *inferType(Scope *sc);
Expression *toExpression();
Expression *toExpression(Type *t = NULL);
Expression *toAssocArrayLiteral();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -137,7 +150,7 @@ struct ExpInitializer : Initializer
Initializer *syntaxCopy();
Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret);
Type *inferType(Scope *sc);
Expression *toExpression();
Expression *toExpression(Type *t = NULL);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
+21 -19
View File
@@ -219,7 +219,7 @@ int VarExp::inlineCost3(InlineCostState *ics)
if (tb->ty == Tstruct)
{
StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->isnested)
if (sd->isNested())
/* An inner struct will be nested inside another function hierarchy than where
* we're inlining into, so don't inline it.
* At least not until we figure out how to 'move' the struct to be nested
@@ -254,7 +254,7 @@ int StructLiteralExp::inlineCost3(InlineCostState *ics)
{
//printf("StructLiteralExp::inlineCost3() %s\n", toChars());
#if DMDV2
if (sd->isnested)
if (sd->isNested())
return COST_MAX;
#endif
return 1;
@@ -594,7 +594,7 @@ Expression *IfStatement::doInline(InlineDoState *ids)
Expression *ReturnStatement::doInline(InlineDoState *ids)
{
//printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : "");
return exp ? exp->doInline(ids) : 0;
return exp ? exp->doInline(ids) : NULL;
}
#if DMDV2
@@ -892,6 +892,8 @@ Expression *TupleExp::doInline(InlineDoState *ids)
TupleExp *ce;
ce = (TupleExp *)copy();
if (e0)
ce->e0 = e0->doInline(ids);
ce->exps = arrayExpressiondoInline(exps, ids);
return ce;
}
@@ -920,10 +922,12 @@ Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids)
Expression *StructLiteralExp::doInline(InlineDoState *ids)
{
if(inlinecopy) return inlinecopy;
StructLiteralExp *ce;
ce = (StructLiteralExp *)copy();
inlinecopy = ce;
ce->elements = arrayExpressiondoInline(elements, ids);
inlinecopy = NULL;
return ce;
}
@@ -1194,14 +1198,6 @@ Statement *ThrowStatement::inlineScan(InlineScanState *iss)
}
Statement *VolatileStatement::inlineScan(InlineScanState *iss)
{
if (statement)
statement = statement->inlineScan(iss);
return this;
}
Statement *LabelStatement::inlineScan(InlineScanState *iss)
{
if (statement)
@@ -1373,6 +1369,8 @@ Expression *TupleExp::inlineScan(InlineScanState *iss)
{ Expression *e = this;
//printf("TupleExp::inlineScan()\n");
if (e0)
e0->inlineScan(iss);
arrayInlineScan(iss, exps);
return e;
@@ -1404,8 +1402,11 @@ Expression *StructLiteralExp::inlineScan(InlineScanState *iss)
{ Expression *e = this;
//printf("StructLiteralExp::inlineScan()\n");
if(stageflags & stageInlineScan) return e;
int old = stageflags;
stageflags |= stageInlineScan;
arrayInlineScan(iss, elements);
stageflags = old;
return e;
}
@@ -1496,7 +1497,8 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
if (type)
{ assert(type->ty == Tfunction);
TypeFunction *tf = (TypeFunction *)(type);
TypeFunction *tf = (TypeFunction *)type;
#if IN_LLVM
// LDC: Only extern(C) varargs count.
if (tf->linkage != LINKd)
@@ -1679,7 +1681,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
// Set up parameters
if (ethis)
{
e = new DeclarationExp(0, ids.vthis);
e = new DeclarationExp(Loc(), ids.vthis);
e->type = Type::tvoid;
if (as)
as->push(new ExpStatement(e->loc, e));
@@ -1719,11 +1721,11 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
ids.from.push(vfrom);
ids.to.push(vto);
de = new DeclarationExp(0, vto);
de = new DeclarationExp(Loc(), vto);
de->type = Type::tvoid;
if (as)
as->push(new ExpStatement(0, de));
as->push(new ExpStatement(Loc(), de));
else
e = Expression::combine(e, de);
}
@@ -1734,7 +1736,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
inlineNest++;
Statement *s = fbody->doInlineStatement(&ids);
as->push(s);
*ps = new ScopeStatement(0, new CompoundStatement(0, as));
*ps = new ScopeStatement(Loc(), new CompoundStatement(Loc(), as));
inlineNest--;
}
else
@@ -1778,7 +1780,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
ei->exp = new ConstructExp(loc, ve, e);
ei->exp->type = ve->type;
DeclarationExp* de = new DeclarationExp(0, vd);
DeclarationExp* de = new DeclarationExp(Loc(), vd);
de->type = Type::tvoid;
// Chain the two together:
+279 -173
View File
@@ -59,22 +59,30 @@ private:
VarDeclarations vars; // corresponding variables
ArrayBase<void> savedId; // id of the previous state of that var
ArrayBase<void> frames; // all previous frame pointers
Expressions savedThis; // all previous values of localThis
/* Global constants get saved here after evaluation, so we never
* have to redo them. This saves a lot of time and memory.
*/
Expressions globalValues; // values of global constants
size_t framepointer; // current frame pointer
size_t maxStackPointer; // most stack we've ever used
size_t framepointer; // current frame pointer
size_t maxStackPointer; // most stack we've ever used
Expression *localThis; // value of 'this', or NULL if none
public:
CtfeStack();
size_t stackPointer();
// The current value of 'this', or NULL if none
Expression *getThis();
// Largest number of stack positions we've used
size_t maxStackUsage();
// return the previous frame
size_t startFrame();
void endFrame(size_t oldframe);
// Start a new stack frame, using the provided 'this'.
void startFrame(Expression *thisexp);
void endFrame();
bool isInCurrentFrame(VarDeclaration *v);
Expression *getValue(VarDeclaration *v);
void setValue(VarDeclaration *v, Expression *e);
@@ -88,13 +96,11 @@ struct InterState
{
InterState *caller; // calling function's InterState
FuncDeclaration *fd; // function being interpreted
size_t framepointer; // frame pointer of previous frame
Statement *start; // if !=NULL, start execution at this statement
Statement *gotoTarget; /* target of EXP_GOTO_INTERPRET result; also
* target of labelled EXP_BREAK_INTERPRET or
* EXP_CONTINUE_INTERPRET. (NULL if no label).
*/
Expression *localThis; // value of 'this', or NULL if none
bool awaitingLvalueReturn; // Support for ref return values:
// Any return to this function should return an lvalue.
InterState();
@@ -113,24 +119,34 @@ size_t CtfeStack::stackPointer()
return values.dim;
}
Expression *CtfeStack::getThis()
{
return localThis;
}
// Largest number of stack positions we've used
size_t CtfeStack::maxStackUsage()
{
return maxStackPointer;
}
// return the previous frame
size_t CtfeStack::startFrame()
void CtfeStack::startFrame(Expression *thisexp)
{
size_t oldframe = framepointer;
frames.push((void *)(size_t)(framepointer));
savedThis.push(localThis);
framepointer = stackPointer();
return oldframe;
localThis = thisexp;
}
void CtfeStack::endFrame(size_t oldframe)
void CtfeStack::endFrame()
{
size_t oldframe = (size_t)(frames[frames.dim-1]);
localThis = savedThis[savedThis.dim-1];
popAll(framepointer);
framepointer = oldframe;
frames.setDim(frames.dim - 1);
savedThis.setDim(savedThis.dim -1);
}
bool CtfeStack::isInCurrentFrame(VarDeclaration *v)
@@ -240,9 +256,9 @@ void printCtfePerformanceStats()
}
Expression * resolveReferences(Expression *e, Expression *thisval);
Expression * resolveReferences(Expression *e);
Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal);
VarDeclaration *findParentVar(Expression *e, Expression *thisval);
VarDeclaration *findParentVar(Expression *e);
Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
Expression *scrubReturnValue(Loc loc, Expression *e);
@@ -299,15 +315,8 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
// Func literals report isNested() even if they are in global scope,
// so we need to check that the parent is a function.
if (isNested() && toParent2()->isFuncDeclaration() && !thisarg && istate)
thisarg = istate->localThis;
thisarg = ctfeStack.getThis();
InterState istatex;
istatex.caller = istate;
istatex.fd = this;
istatex.localThis = thisarg;
istatex.framepointer = ctfeStack.startFrame();
Expressions vsave; // place to save previous parameter values
size_t dim = 0;
if (needThis() && !thisarg)
{ // error, no this. Prevent segfault.
@@ -320,16 +329,19 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
return EXP_CANT_INTERPRET;
}
static int evaluatingArgs = 0;
// Place to hold all the arguments to the function while
// we are evaluating them.
Expressions eargs;
if (arguments)
{
dim = arguments->dim;
assert(!dim || (parameters && (parameters->dim == dim)));
vsave.setDim(dim);
/* Evaluate all the arguments to the function,
* store the results in eargs[]
*/
Expressions eargs;
eargs.setDim(dim);
for (size_t i = 0; i < dim; i++)
{ Expression *earg = (*arguments)[i];
@@ -387,6 +399,18 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
}
eargs[i] = earg;
}
}
// Now that we've evaluated all the arguments, we can start the frame
// (this is the moment when the 'call' actually takes place).
InterState istatex;
istatex.caller = istate;
istatex.fd = this;
ctfeStack.startFrame(thisarg);
if (arguments)
{
for (size_t i = 0; i < dim; i++)
{ Expression *earg = eargs[i];
@@ -471,7 +495,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
// Leave the function
--CtfeStatus::callDepth;
ctfeStack.endFrame(istatex.framepointer);
ctfeStack.endFrame();
// If fell off the end of a void function, return void
if (!e && type->toBasetype()->nextOf()->ty == Tvoid)
@@ -731,8 +755,16 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
{
if (e->op == TOKclassreference)
{
error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars());
return EXP_CANT_INTERPRET;
StructLiteralExp *se = ((ClassReferenceExp*)e)->value;
se->ownedByCtfe = false;
if (!(se->stageflags & stageScrub))
{
int old = se->stageflags;
se->stageflags |= stageScrub;
if (!scrubArray(loc, se->elements, true))
return EXP_CANT_INTERPRET;
se->stageflags = old;
}
}
if (e->op == TOKvoid)
{
@@ -747,8 +779,14 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
{
StructLiteralExp *se = (StructLiteralExp *)e;
se->ownedByCtfe = false;
if (!scrubArray(loc, se->elements, true))
return EXP_CANT_INTERPRET;
if (!(se->stageflags & stageScrub))
{
int old = se->stageflags;
se->stageflags |= stageScrub;
if (!scrubArray(loc, se->elements, true))
return EXP_CANT_INTERPRET;
se->stageflags = old;
}
}
if (e->op == TOKstring)
{
@@ -1361,12 +1399,11 @@ Expression *Expression::interpret(InterState *istate, CtfeGoal goal)
Expression *ThisExp::interpret(InterState *istate, CtfeGoal goal)
{
while (istate && !istate->localThis)
istate = istate->caller;
if (istate && istate->localThis && istate->localThis->op == TOKstructliteral)
return istate->localThis;
if (istate && istate->localThis)
return istate->localThis->interpret(istate, goal);
Expression *localThis = ctfeStack.getThis();
if (localThis && localThis->op == TOKstructliteral)
return localThis;
if (localThis)
return localThis->interpret(istate, goal);
error("value of 'this' is not known at compile time");
return EXP_CANT_INTERPRET;
}
@@ -1407,11 +1444,11 @@ Expression *StringExp::interpret(InterState *istate, CtfeGoal goal)
* In D2, we also disallow casts of read-only literals to mutable,
* though it isn't strictly necessary.
*/
#if DMDV2
#if 0 //DMDV2
// Fixed-length char arrays always get duped later anyway.
if (type->ty == Tsarray)
return this;
if (!(((TypeNext *)type)->next->mod & (MODconst | MODimmutable)))
if (!(((TypeNext *)type)->next->toBasetype()->mod & (MODconst | MODimmutable)))
{ // It seems this happens only when there has been an explicit cast
error("cannot cast a read-only string literal to mutable in CTFE");
return EXP_CANT_INTERPRET;
@@ -1437,12 +1474,42 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal)
{
return this;
}
if (isTypeInfo_Class(type) && offset == 0)
{
return this;
}
if (type->ty != Tpointer)
{ // Probably impossible
error("Cannot interpret %s at compile time", toChars());
return EXP_CANT_INTERPRET;
}
Type *pointee = ((TypePointer *)type)->next;
if ( var->isThreadlocal())
{
error("cannot take address of thread-local variable %s at compile time", var->toChars());
return EXP_CANT_INTERPRET;
}
// Check for taking an address of a shared variable.
// If the shared variable is an array, the offset might not be zero.
VarDeclaration *vd = var->isVarDeclaration();
Type *fromType = NULL;
if (var->type->ty == Tarray || var->type->ty == Tsarray)
{
fromType = ((TypeArray *)(var->type))->next;
}
if ( var->isDataseg() && (
(offset == 0 && isSafePointerCast(var->type, pointee)) ||
(fromType && isSafePointerCast(fromType, pointee))
) && !(vd && vd->init &&
#if DMDV2
(var->isConst() || var->isImmutable())
#else
var>isConst()
#endif
))
{
return this;
}
Expression *val = getVarExp(loc, istate, var, goal);
if (val == EXP_CANT_INTERPRET)
return val;
@@ -1534,12 +1601,13 @@ Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal)
// -------------------------------------------------------------
// The variable used in a dotvar, index, or slice expression,
// after 'out', 'ref', and 'this' have been removed.
Expression * resolveReferences(Expression *e, Expression *thisval)
Expression * resolveReferences(Expression *e)
{
for(;;)
{
if (e->op == TOKthis)
{
Expression *thisval = ctfeStack.getThis();
assert(thisval);
assert(e != thisval);
e = thisval;
@@ -1579,11 +1647,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
{
Expression *e = EXP_CANT_INTERPRET;
VarDeclaration *v = d->isVarDeclaration();
#if IN_LLVM
StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration();
#else
SymbolDeclaration *s = d->isSymbolDeclaration();
#endif
if (v)
{
#if DMDV2
@@ -1596,7 +1660,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
#else
if (v->isConst() && v->init && !v->isCTFE())
#endif
{ e = v->init->toExpression();
{ e = v->init->toExpression(v->type);
if (e && (e->op == TOKconstruct || e->op == TOKblit))
{ AssignExp *ae = (AssignExp *)e;
e = ae->e2;
@@ -1693,20 +1757,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
}
else if (s)
{ // Struct static initializers, for example
#if !IN_LLVM
if (s->dsym->toInitializer() == s->sym)
#endif
{ e = s->dsym->type->defaultInitLiteral(loc);
e = e->semantic(NULL);
if (e->op == TOKerror)
e = EXP_CANT_INTERPRET;
else // Convert NULL to VoidExp
e = e->interpret(istate, goal);
}
#if !IN_LLVM
else
error(loc, "cannot interpret symbol %s at compile time", s->toChars());
#endif
e = s->dsym->type->defaultInitLiteral(loc);
e = e->semantic(NULL);
if (e->op == TOKerror)
e = EXP_CANT_INTERPRET;
else // Convert NULL to VoidExp
e = e->interpret(istate, goal);
}
else
error(loc, "cannot interpret declaration %s at compile time", d->toChars());
@@ -1770,8 +1826,9 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
if (!v2->isDataseg() || v2->isCTFE())
ctfeStack.push(v2);
}
return NULL;
}
if (!v->isDataseg() || v->isCTFE())
if (!(v->isDataseg() || v->storage_class & STCmanifest) || v->isCTFE())
ctfeStack.push(v);
Dsymbol *s = v->toAlias();
if (s == v && !v->isStatic() && v->init)
@@ -1847,6 +1904,12 @@ Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal)
#endif
Expressions *expsx = NULL;
if (e0)
{
if (e0->interpret(istate) == EXP_CANT_INTERPRET)
return EXP_CANT_INTERPRET;
}
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (*exps)[i];
Expression *ex;
@@ -2223,31 +2286,27 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
return EXP_CANT_INTERPRET;
}
Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *))
Expression *UnaExp::interpret(InterState *istate, CtfeGoal goal)
{ Expression *e;
Expression *e1;
#if LOG
printf("%s UnaExp::interpretCommon() %s\n", loc.toChars(), toChars());
printf("%s UnaExp::interpret() %s\n", loc.toChars(), toChars());
#endif
e1 = this->e1->interpret(istate);
if (exceptionOrCantInterpret(e1))
return e1;
e = (*fp)(type, e1);
switch(op)
{
case TOKneg: e = Neg(type, e1); break;
case TOKtilde: e = Com(type, e1); break;
case TOKnot: e = Not(type, e1); break;
case TOKtobool: e = Bool(type, e1); break;
default: assert(0);
}
return e;
}
#define UNA_INTERPRET(op) \
Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \
{ \
return interpretCommon(istate, goal, &op); \
}
UNA_INTERPRET(Neg)
UNA_INTERPRET(Com)
UNA_INTERPRET(Not)
UNA_INTERPRET(Bool)
typedef Expression *(*fp_t)(Type *, Expression *, Expression *);
Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp)
@@ -2314,31 +2373,8 @@ Lcant:
return EXP_CANT_INTERPRET;
}
#define BIN_INTERPRET(op) \
Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \
{ \
return interpretCommon(istate, goal, &op); \
}
BIN_INTERPRET(Add)
BIN_INTERPRET(Min)
BIN_INTERPRET(Mul)
BIN_INTERPRET(Div)
BIN_INTERPRET(Mod)
BIN_INTERPRET(Shl)
BIN_INTERPRET(Shr)
BIN_INTERPRET(Ushr)
BIN_INTERPRET(And)
BIN_INTERPRET(Or)
BIN_INTERPRET(Xor)
#if DMDV2
BIN_INTERPRET(Pow)
#endif
typedef int (*fp2_t)(Loc loc, enum TOK, Expression *, Expression *);
Expression *BinExp::interpretCompareCommon(InterState *istate, CtfeGoal goal, fp2_t fp)
{
Expression *e1;
@@ -2390,47 +2426,59 @@ Expression *BinExp::interpretCompareCommon(InterState *istate, CtfeGoal goal, fp
return new IntegerExp(loc, cmp, type);
}
#define BIN_INTERPRET2(op, opfunc) \
Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \
{ \
return interpretCompareCommon(istate, goal, &opfunc); \
Expression *BinExp::interpret(InterState *istate, CtfeGoal goal)
{
switch(op)
{
case TOKadd: return interpretCommon(istate, goal, &Add);
case TOKmin: return interpretCommon(istate, goal, &Min);
case TOKmul: return interpretCommon(istate, goal, &Mul);
case TOKdiv: return interpretCommon(istate, goal, &Div);
case TOKmod: return interpretCommon(istate, goal, &Mod);
case TOKshl: return interpretCommon(istate, goal, &Shl);
case TOKshr: return interpretCommon(istate, goal, &Shr);
case TOKushr: return interpretCommon(istate, goal, &Ushr);
case TOKand: return interpretCommon(istate, goal, &And);
case TOKor: return interpretCommon(istate, goal, &Or);
case TOKxor: return interpretCommon(istate, goal, &Xor);
#if DMDV2
case TOKpow: return interpretCommon(istate, goal, &Pow);
#endif
case TOKequal:
case TOKnotequal:
return interpretCompareCommon(istate, goal, &ctfeEqual);
case TOKidentity:
case TOKnotidentity:
return interpretCompareCommon(istate, goal, &ctfeIdentity);
case TOKlt:
case TOKle:
case TOKgt:
case TOKge:
case TOKleg:
case TOKlg:
case TOKunord:
case TOKue:
case TOKug:
case TOKuge:
case TOKul:
case TOKule:
return interpretCompareCommon(istate, goal, &ctfeCmp);
default:
assert(0);
return NULL;
}
}
BIN_INTERPRET2(Equal, ctfeEqual)
BIN_INTERPRET2(Identity, ctfeIdentity)
BIN_INTERPRET2(Cmp, ctfeCmp)
/* Helper functions for BinExp::interpretAssignCommon
*/
// Return true if e is derived from UnaryExp.
// Consider moving this function into Expression.
UnaExp *isUnaExp(Expression *e)
{
switch (e->op)
{
case TOKdotvar:
case TOKindex:
case TOKslice:
case TOKcall:
case TOKdot:
case TOKdotti:
case TOKdottype:
case TOKcast:
return (UnaExp *)e;
default:
break;
}
return NULL;
}
// Returns the variable which is eventually modified, or NULL if an rvalue.
// thisval is the current value of 'this'.
VarDeclaration * findParentVar(Expression *e, Expression *thisval)
VarDeclaration * findParentVar(Expression *e)
{
for (;;)
{
e = resolveReferences(e, thisval);
e = resolveReferences(e);
if (e->op == TOKvar)
break;
if (e->op == TOKindex)
@@ -2449,7 +2497,6 @@ VarDeclaration * findParentVar(Expression *e, Expression *thisval)
return v;
}
Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post)
{
#if LOG
@@ -2525,7 +2572,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
* can be dealt with by making this a non-ref assign (y = x.dup).
* Otherwise it's a big mess.
*/
VarDeclaration * targetVar = findParentVar(e2, istate->localThis);
VarDeclaration * targetVar = findParentVar(e2);
if (!(targetVar && targetVar->isConst()))
wantRef = true;
// slice assignment of static arrays is not reference assignment
@@ -2566,7 +2613,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
// First, deal with this = e; and call() = e;
if (e1->op == TOKthis)
{
e1 = istate->localThis;
e1 = ctfeStack.getThis();
}
if (e1->op == TOKcall)
{
@@ -2581,7 +2628,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
// f() = e2, when f returns an array, is always a slice assignment.
// Convert into arr[0..arr.length] = e2
e1 = new SliceExp(loc, e1,
new IntegerExp(0, 0, Type::tsize_t),
new IntegerExp(Loc(), 0, Type::tsize_t),
ArrayLength(Type::tsize_t, e1));
e1->type = type;
}
@@ -2636,7 +2683,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
return oldval;
while (oldval->op == TOKvar)
{
oldval = resolveReferences(oldval, istate->localThis);
oldval = resolveReferences(oldval);
oldval = oldval->interpret(istate);
if (exceptionOrCantInterpret(oldval))
return oldval;
@@ -2705,7 +2752,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
{ // Get the old array literal.
oldval = e1->interpret(istate);
while (oldval->op == TOKvar)
{ oldval = resolveReferences(oldval, istate->localThis);
{ oldval = resolveReferences(oldval);
oldval = oldval->interpret(istate);
}
}
@@ -2757,14 +2804,14 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
// -------------------------------------------------
// Make sure we're not trying to modify a global or static variable
// We do this by locating the ultimate parent variable which gets modified.
VarDeclaration * ultimateVar = findParentVar(e1, istate->localThis);
VarDeclaration * ultimateVar = findParentVar(e1);
if (ultimateVar && ultimateVar->isDataseg() && !ultimateVar->isCTFE())
{ // Can't modify global or static data
error("%s cannot be modified at compile time", ultimateVar->toChars());
return EXP_CANT_INTERPRET;
}
e1 = resolveReferences(e1, istate->localThis);
e1 = resolveReferences(e1);
// Unless we have a simple var assignment, we're
// only modifying part of the variable. So we need to make sure
@@ -2825,7 +2872,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
ie = (IndexExp *)ie->e1;
++depth;
}
Expression *aggregate = resolveReferences(ie->e1, istate->localThis);
Expression *aggregate = resolveReferences(ie->e1);
Expression *oldagg = aggregate;
// Get the AA to be modified. (We do an LvalueRef interpret, unless it
// is a simple ref parameter -- in which case, we just want the value)
@@ -3075,7 +3122,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
ArrayLiteralExp *existingAE = NULL;
StringExp *existingSE = NULL;
Expression *aggregate = resolveReferences(ie->e1, istate->localThis);
Expression *aggregate = resolveReferences(ie->e1);
// Set the index to modify, and check that it is in range
dinteger_t indexToModify = index->toInteger();
@@ -3101,6 +3148,11 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (aggregate->op != TOKslice && aggregate->op != TOKstring &&
aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral)
{
if (aggregate->op == TOKsymoff)
{
error("mutable variable %s cannot be modified at compile time, even through a pointer", ((SymOffExp *)aggregate)->var->toChars());
return EXP_CANT_INTERPRET;
}
if (indexToModify != 0)
{
error("pointer index [%lld] lies outside memory block [0..1]", indexToModify);
@@ -3251,6 +3303,11 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
&& oldval->op != TOKslice && oldval->op != TOKnull)
{
if (oldval->op == TOKsymoff)
{
error("pointer %s cannot be sliced at compile time (it points to a static variable)", sexp->e1->toChars());
return EXP_CANT_INTERPRET;
}
if (assignmentToSlicedPointer)
{
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
@@ -3298,7 +3355,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (upperbound == lowerbound)
return newval;
Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1, istate->localThis);
Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1);
dinteger_t firstIndex = lowerbound;
ArrayLiteralExp *existingAE = NULL;
@@ -3515,29 +3572,30 @@ Expression *AssignExp::interpret(InterState *istate, CtfeGoal goal)
return interpretAssignCommon(istate, goal, NULL);
}
#define BIN_ASSIGN_INTERPRET_CTFE(op, ctfeOp) \
Expression *op##AssignExp::interpret(InterState *istate, CtfeGoal goal) \
{ \
return interpretAssignCommon(istate, goal, &ctfeOp); \
}
#define BIN_ASSIGN_INTERPRET(op) BIN_ASSIGN_INTERPRET_CTFE(op, op)
BIN_ASSIGN_INTERPRET(Add)
BIN_ASSIGN_INTERPRET(Min)
BIN_ASSIGN_INTERPRET_CTFE(Cat, ctfeCat)
BIN_ASSIGN_INTERPRET(Mul)
BIN_ASSIGN_INTERPRET(Div)
BIN_ASSIGN_INTERPRET(Mod)
BIN_ASSIGN_INTERPRET(Shl)
BIN_ASSIGN_INTERPRET(Shr)
BIN_ASSIGN_INTERPRET(Ushr)
BIN_ASSIGN_INTERPRET(And)
BIN_ASSIGN_INTERPRET(Or)
BIN_ASSIGN_INTERPRET(Xor)
Expression *BinAssignExp::interpret(InterState *istate, CtfeGoal goal)
{
switch(op)
{
case TOKaddass: return interpretAssignCommon(istate, goal, &Add);
case TOKminass: return interpretAssignCommon(istate, goal, &Min);
case TOKcatass: return interpretAssignCommon(istate, goal, &ctfeCat);
case TOKmulass: return interpretAssignCommon(istate, goal, &Mul);
case TOKdivass: return interpretAssignCommon(istate, goal, &Div);
case TOKmodass: return interpretAssignCommon(istate, goal, &Mod);
case TOKshlass: return interpretAssignCommon(istate, goal, &Shl);
case TOKshrass: return interpretAssignCommon(istate, goal, &Shr);
case TOKushrass: return interpretAssignCommon(istate, goal, &Ushr);
case TOKandass: return interpretAssignCommon(istate, goal, &And);
case TOKorass: return interpretAssignCommon(istate, goal, &Or);
case TOKxorass: return interpretAssignCommon(istate, goal, &Xor);
#if DMDV2
BIN_ASSIGN_INTERPRET(Pow)
case TOKpowass: return interpretAssignCommon(istate, goal, &Pow);
#endif
default:
assert(0);
return NULL;
}
}
Expression *PostExp::interpret(InterState *istate, CtfeGoal goal)
{
@@ -3897,7 +3955,7 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
Expression * pe = ((PtrExp*)ecall)->e1;
if (pe->op == TOKvar) {
VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration();
if (vd && vd->getValue() && vd->getValue()->op == TOKsymoff)
if (vd && vd->hasValue() && vd->getValue()->op == TOKsymoff)
fd = ((SymOffExp *)vd->getValue())->var->isFuncDeclaration();
else
{
@@ -3938,7 +3996,7 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
else if (ecall->op == TOKvar)
{
VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration();
if (vd && vd->getValue())
if (vd && vd->hasValue())
ecall = vd->getValue();
else // Calling a function
fd = ((VarExp *)e1)->var->isFuncDeclaration();
@@ -3959,7 +4017,7 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
if (!tf)
{ // DAC: This should never happen, it's an internal compiler error.
{ // This should never happen, it's an internal compiler error.
//printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall);
if (ecall->op == TOKidentifier)
error("cannot evaluate %s at compile time. Circular reference?", toChars());
@@ -3988,8 +4046,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
{ // Make a virtual function call.
Expression *thisval = pthis;
if (pthis->op == TOKvar)
{ assert(((VarExp*)thisval)->var->isVarDeclaration());
thisval = ((VarExp*)thisval)->var->isVarDeclaration()->getValue();
{
VarDeclaration *vthis = ((VarExp*)thisval)->var->isVarDeclaration();
assert(vthis);
thisval = getVarExp(loc, istate, vthis, ctfeNeedLvalue);
// If it is a reference, resolve it
if (thisval->op != TOKnull && thisval->op != TOKclassreference)
thisval = pthis->interpret(istate);
@@ -4042,6 +4102,8 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
}
return e;
}
if (fd->dArrayOp)
return fd->dArrayOp->interpret(istate, arguments, pthis);
if (!fd->fbody)
{
error("%s cannot be interpreted at compile time,"
@@ -4076,7 +4138,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
InterState istateComma;
if (!istate && firstComma->e1->op == TOKdeclaration)
{
ctfeStack.startFrame();
ctfeStack.startFrame(NULL);
istate = &istateComma;
}
@@ -4104,7 +4166,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
if (exceptionOrCantInterpret(newval))
{
if (istate == &istateComma)
ctfeStack.endFrame(0);
ctfeStack.endFrame();
return newval;
}
if (newval != EXP_VOID_INTERPRET)
@@ -4126,7 +4188,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
}
// If we created a temporary stack frame, end it now.
if (istate == &istateComma)
ctfeStack.endFrame(0);
ctfeStack.endFrame();
return e;
}
@@ -4227,6 +4289,11 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
}
else
{ // Pointer to a non-array variable
if (agg->op == TOKsymoff)
{
error("mutable variable %s cannot be read at compile time, even through a pointer", ((SymOffExp *)agg)->var->toChars());
return EXP_CANT_INTERPRET;
}
if ((indx + ofs) != 0)
{
error("pointer index [%lld] lies outside memory block [0..1]",
@@ -4380,6 +4447,11 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
error("cannot slice null pointer %s", this->e1->toChars());
return EXP_CANT_INTERPRET;
}
if (agg->op == TOKsymoff)
{
error("slicing pointers to static variables is not supported in CTFE");
return EXP_CANT_INTERPRET;
}
if (agg->op != TOKarrayliteral && agg->op != TOKstring)
{
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
@@ -4681,17 +4753,21 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
return e;
}
}
if (e1->op == TOKvar)
if (e1->op == TOKvar || e1->op == TOKsymoff)
{ // type painting operation
Type *origType = ((VarExp *)e1)->var->type;
Type *origType = (e1->op == TOKvar) ? ((VarExp *)e1)->var->type :
((SymOffExp *)e1)->var->type;
if (castBackFromVoid && !isSafePointerCast(origType, pointee))
{
error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE",
origType->toChars(), pointee->toChars());
return EXP_CANT_INTERPRET;
}
e = new VarExp(loc, ((VarExp *)e1)->var);
e->type = type;
if (e1->op == TOKvar)
e = new VarExp(loc, ((VarExp *)e1)->var);
else
e = new SymOffExp(loc, ((SymOffExp *)e1)->var, 0);
e->type = to;
return e;
}
@@ -4833,12 +4909,39 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
#else // this is required for D1, where structs return *this instead of 'this'.
else if (e1->op == TOKthis)
{
if(istate->localThis)
return istate->localThis->interpret(istate);
if (ctfeStack.getThis())
return ctfeStack.getThis()->interpret(istate);
}
#endif
else
{ // It's possible we have an array bounds error. We need to make sure it
{
// Check for .classinfo, which is lowered in the semantic pass into **(class).
if (e1->op == TOKstar && e1->type->ty == Tpointer && isTypeInfo_Class(e1->type->nextOf()))
{
e = (((PtrExp *)e1)->e1)->interpret(istate, ctfeNeedLvalue);
if (exceptionOrCantInterpret(e))
return e;
if (e->op == TOKnull)
{
error("Null pointer dereference evaluating typeid. '%s' is null", ((PtrExp *)e1)->e1->toChars());
return EXP_CANT_INTERPRET;
}
if (e->op != TOKclassreference)
{ error("CTFE internal error determining classinfo");
return EXP_CANT_INTERPRET;
}
ClassDeclaration *cd = ((ClassReferenceExp *)e)->originalClass();
assert(cd);
// Create the classinfo, if it doesn't yet exist.
// TODO: This belongs in semantic, CTFE should not have to do this.
if (!cd->vclassinfo)
cd->vclassinfo = new TypeInfoClassDeclaration(cd->type);
e = new SymOffExp(loc, cd->vclassinfo, 0);
e->type = type;
return e;
}
// It's possible we have an array bounds error. We need to make sure it
// errors with this line number, not the one where the pointer was set.
e = e1->interpret(istate, ctfeNeedLvalue);
if (exceptionOrCantInterpret(e))
@@ -4846,7 +4949,10 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
if (!(e->op == TOKvar || e->op == TOKdotvar || e->op == TOKindex
|| e->op == TOKslice || e->op == TOKaddress))
{
error("dereference of invalid pointer '%s'", e->toChars());
if (e->op == TOKsymoff)
error("cannot dereference pointer to static variable %s at compile time", ((SymOffExp *)e)->var->toChars());
else
error("dereference of invalid pointer '%s'", e->toChars());
return EXP_CANT_INTERPRET;
}
if (goal != ctfeNeedLvalue)
+15 -4
View File
@@ -68,7 +68,6 @@ 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, Expressions* expressions);
void property(const char *name, enum TRUST trust);
void property(const char *name, enum PURE purity);
void property(const char *name, enum LINK linkage);
@@ -545,7 +544,7 @@ void TypeQualified::toJson(JsonOut *json) // ident.ident.ident.etc
json->arrayStart();
for (size_t i = 0; i < idents.dim; i++)
{ Identifier *ident = idents[i];
{ Object *ident = idents[i];
json->item(ident->toChars());
}
@@ -629,9 +628,11 @@ void Dsymbol::toJson(JsonOut *json)
void Dsymbol::jsonProperties(JsonOut *json)
{
json->property("name", toChars());
if (!isTemplateDeclaration()) // TemplateDeclaration::kind() acts weird sometimes
{
json->property("name", toChars());
json->property("kind", kind());
}
if (prot() != PROTpublic)
json->property("protection", Pprotectionnames[prot()]);
@@ -848,6 +849,16 @@ void Declaration::jsonProperties(JsonOut *json)
}
}
void TemplateDeclaration::jsonProperties(JsonOut *json)
{
Dsymbol::jsonProperties(json);
if (onemember && onemember->isCtorDeclaration())
json->property("name", "this"); // __ctor -> this
else
json->property("name", ident->toChars()); // Foo(T) -> Foo
}
void TypedefDeclaration::toJson(JsonOut *json)
{
json->objectStart();
@@ -1071,7 +1082,7 @@ void VarDeclaration::toJson(JsonOut *json)
if (init)
json->property("init", init->toChars());
if (storage_class & STCfield)
if (isField())
json->property("offset", offset);
if (alignment && alignment != STRUCTALIGN_DEFAULT)
+15 -9
View File
@@ -38,7 +38,7 @@
#if _WIN32 && __DMC__
// from \dm\src\include\setlocal.h
extern "C" char * __cdecl __locale_decpoint;
extern "C" const char * __cdecl __locale_decpoint;
#endif
extern int HtmlNamedEntity(unsigned char *p, size_t length);
@@ -96,7 +96,7 @@ void *Token::operator new(size_t size)
#ifdef DEBUG
void Token::print()
{
fprintf(stdmsg, "%s\n", toChars());
fprintf(stderr, "%s\n", toChars());
}
#endif
@@ -678,7 +678,7 @@ void Lexer::scan(Token *t)
}
else if (id == Id::VENDOR)
{
t->ustring = (unsigned char *)"LDC";
t->ustring = (unsigned char *)global.compiler.vendor;
goto Lstr;
}
else if (id == Id::TIMESTAMP)
@@ -909,6 +909,8 @@ void Lexer::scan(Token *t)
}
continue;
}
default:
break;
}
t->value = TOKdiv;
return;
@@ -1911,7 +1913,9 @@ TOK Lexer::number(Token *t)
enum STATE state;
enum FLAGS
{ FLAGS_decimal = 1, // decimal
{
FLAGS_none = 0,
FLAGS_decimal = 1, // decimal
FLAGS_unsigned = 2, // u or U suffix
FLAGS_long = 4, // l or L suffix
};
@@ -2175,7 +2179,7 @@ done:
switch (flags)
{
case 0:
case FLAGS_none:
/* Octal or Hexadecimal constant.
* First that fits: int, uint, long, ulong
*/
@@ -2359,7 +2363,7 @@ done:
stringbuffer.writeByte(0);
#if _WIN32 && __DMC__
char *save = __locale_decpoint;
const char *save = __locale_decpoint;
__locale_decpoint = ".";
#endif
#ifdef IN_GCC
@@ -2794,7 +2798,7 @@ Identifier *Lexer::uniqueId(const char *s, int num)
{ char buffer[32];
size_t slen = strlen(s);
assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer));
assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer) / sizeof(buffer[0]));
sprintf(buffer, "%s%d", s, num);
return idPool(buffer);
}
@@ -2933,13 +2937,15 @@ static Keyword keywords[] =
#if DMDV2
{ "pure", TOKpure },
{ "nothrow", TOKnothrow },
{ "__thread", TOKtls },
{ "__gshared", TOKgshared },
{ "__traits", TOKtraits },
{ "__vector", TOKvector },
{ "__overloadset", TOKoverloadset },
{ "__FILE__", TOKfile },
{ "__LINE__", TOKline },
{ "__MODULE__", TOKmodulestring },
{ "__FUNCTION__", TOKfuncstring },
{ "__PRETTY_FUNCTION__", TOKprettyfunc },
{ "shared", TOKshared },
{ "immutable", TOKimmutable },
#endif
@@ -2959,7 +2965,7 @@ void Lexer::initKeywords()
{
size_t nkeywords = sizeof(keywords) / sizeof(keywords[0]);
stringtable.init(6151);
stringtable._init(6151);
if (global.params.Dversion == 1)
nkeywords -= 2;
+5 -2
View File
@@ -161,10 +161,12 @@ enum TOK
TOKoverloadset,
TOKpure,
TOKnothrow,
TOKtls,
TOKgshared,
TOKline,
TOKfile,
TOKmodulestring,
TOKfuncstring,
TOKprettyfunc,
TOKshared,
TOKat,
TOKpow,
@@ -263,7 +265,9 @@ struct Token
Token() : next(NULL) {}
int isKeyword();
#ifdef DEBUG
void print();
#endif
const char *toChars();
static const char *toChars(enum TOK);
};
@@ -310,7 +314,6 @@ struct Lexer
TOK escapeStringConstant(Token *t, int wide);
TOK charConstant(Token *t, int wide);
void stringPostfix(Token *t);
unsigned wchar(unsigned u);
TOK number(Token *t);
TOK inreal(Token *t);
void error(const char *format, ...);
+32 -15
View File
@@ -109,7 +109,7 @@ L1:
return id;
}
char *Declaration::mangle(bool isv)
const char *Declaration::mangle(bool isv)
#if __DMC__
__out(result)
{
@@ -157,7 +157,7 @@ char *Declaration::mangle(bool isv)
return ident->toChars();
default:
fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage);
fprintf(stderr, "'%s', linkage = %d\n", toChars(), linkage);
assert(0);
}
}
@@ -171,7 +171,7 @@ char *Declaration::mangle(bool isv)
return p;
}
char *FuncDeclaration::mangle(bool isv)
const char *FuncDeclaration::mangle(bool isv)
#if __DMC__
__out(result)
{
@@ -180,6 +180,9 @@ char *FuncDeclaration::mangle(bool isv)
__body
#endif
{
if (mangleOverride)
return mangleOverride;
if (isMain())
return (char *)"_Dmain";
@@ -190,22 +193,36 @@ char *FuncDeclaration::mangle(bool isv)
return Declaration::mangle(isv);
}
const char *VarDeclaration::mangle(bool isv)
#if __DMC__
__out(result)
{
assert(strlen(result) > 0);
}
__body
#endif
{
if (mangleOverride)
return mangleOverride;
char *TypedefDeclaration::mangle(bool isv)
return Declaration::mangle();
}
const char *TypedefDeclaration::mangle(bool isv)
{
//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
return Dsymbol::mangle(isv);
}
char *AggregateDeclaration::mangle(bool isv)
const char *AggregateDeclaration::mangle(bool isv)
{
#if 1
//printf("AggregateDeclaration::mangle() '%s'\n", toChars());
if (Dsymbol *p = toParent2())
{ if (FuncDeclaration *fd = p->isFuncDeclaration())
{ // This might be the Voldemort Type
char *id = Dsymbol::mangle(fd->inferRetType || getFuncTemplateDecl(fd));
const char *id = Dsymbol::mangle(fd->inferRetType || getFuncTemplateDecl(fd));
//printf("isv ad %s, %s\n", toChars(), id);
return id;
}
@@ -214,13 +231,13 @@ char *AggregateDeclaration::mangle(bool isv)
return Dsymbol::mangle(isv);
}
char *StructDeclaration::mangle(bool isv)
const char *StructDeclaration::mangle(bool isv)
{
//printf("StructDeclaration::mangle() '%s'\n", toChars());
return AggregateDeclaration::mangle(isv);
}
char *ClassDeclaration::mangle(bool isv)
const char *ClassDeclaration::mangle(bool isv)
{
Dsymbol *parentsave = parent;
@@ -248,13 +265,13 @@ char *ClassDeclaration::mangle(bool isv)
)
parent = NULL;
char *id = AggregateDeclaration::mangle(isv);
const char *id = AggregateDeclaration::mangle(isv);
parent = parentsave;
return id;
}
char *TemplateInstance::mangle(bool isv)
const char *TemplateInstance::mangle(bool isv)
{
OutBuffer buf;
@@ -264,15 +281,15 @@ char *TemplateInstance::mangle(bool isv)
printf(" parent = %s %s", parent->kind(), parent->toChars());
printf("\n");
#endif
char *id = ident ? ident->toChars() : toChars();
const char *id = ident ? ident->toChars() : toChars();
if (!tempdecl)
error("is not defined");
else
{
Dsymbol *par = isnested || isTemplateMixin() ? parent : tempdecl->parent;
Dsymbol *par = enclosing || isTemplateMixin() ? parent : tempdecl->parent;
if (par)
{
char *p = par->mangle();
const char *p = par->mangle();
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
@@ -287,7 +304,7 @@ char *TemplateInstance::mangle(bool isv)
char *Dsymbol::mangle(bool isv)
const char *Dsymbol::mangle(bool isv)
{
OutBuffer buf;
char *id;
@@ -301,7 +318,7 @@ char *Dsymbol::mangle(bool isv)
id = ident ? ident->toChars() : toChars();
if (parent)
{
char *p = parent->mangle(isv);
const char *p = parent->mangle(isv);
if (p[0] == '_' && p[1] == 'D')
p += 2;
buf.writestring(p);
+148 -45
View File
@@ -26,6 +26,7 @@
#if !IN_LLVM
#include "async.h"
#endif
#include "target.h"
#include "mars.h"
#include "module.h"
@@ -59,7 +60,7 @@ static bool parse_arch(size_t argc, char** argv, bool is64bit);
Global global;
Global::Global()
void Global::init()
{
mars_ext = "d";
sym_ext = "d";
@@ -99,14 +100,16 @@ Global::Global()
version = "v"
#include "verstr.h"
;
compiler.vendor = "Digital Mars D";
#endif
#if IN_LLVM
version = "v2.062";
version = "v2.063";
ldc_version = "trunk";
llvm_version = "LLVM " LDC_LLVM_VERSION_STRING;
compiler.vendor = "LDC";
#endif
global.structalign = STRUCTALIGN_DEFAULT;
main_d = "__main.d";
// This should only be used as a global, so the other fields are
// automatically initialized to zero when the program is loaded.
@@ -213,24 +216,24 @@ void verrorPrint(Loc loc, const char *header, const char *format, va_list ap,
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
fprintf(stderr, "%s: ", p);
mem.free(p);
fputs(header, stdmsg);
fputs(header, stderr);
if (p1)
fprintf(stdmsg, "%s ", p1);
fprintf(stderr, "%s ", p1);
if (p2)
fprintf(stdmsg, "%s ", p2);
fprintf(stderr, "%s ", p2);
#if _MSC_VER
// MS doesn't recognize %zu format
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stdmsg, "%s", tmp.toChars());
fprintf(stderr, "%s", tmp.toChars());
#else
vfprintf(stdmsg, format, ap);
vfprintf(stderr, format, ap);
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
fprintf(stderr, "\n");
fflush(stderr);
}
// header is "Error: " by default (see mars.h)
@@ -317,8 +320,8 @@ void usage()
#else
const char fpic[] = "";
#endif
printf("DMD%d D Compiler %s\n%s %s\n",
sizeof(size_t) * 8,
printf("DMD%llu D Compiler %s\n%s %s\n",
(unsigned long long) sizeof(size_t) * 8,
global.version, global.copyright, global.written);
printf("\
Documentation: http://dlang.org/\n\
@@ -329,6 +332,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\
-D generate documentation\n\
-Dddocdir write documentation file to docdir directory\n\
-Dffilename write documentation file to filename\n\
@@ -359,23 +363,24 @@ Usage:\n\
" -m32 generate 32 bit code\n\
-m64 generate 64 bit code\n"
#endif
" -man open web browser on manual page\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\
-O optimize\n\
-o- do not write object file\n\
-odobjdir write object & library files to directory objdir\n\
-offilename name output file to filename\n\
-op do not strip paths from source file\n\
-op preserve source path for output files\n\
-profile profile runtime performance of generated code\n\
-property enforce property syntax\n\
-quiet suppress unnecessary messages\n\
-release compile release version\n\
-run srcfile args... run resulting program, passing args\n"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
" -shared generate shared library\n"
#endif
" -unittest compile in unit tests\n\
-run srcfile args... run resulting program, passing args\n\
-shared generate shared library (DLL)\n\
-transition=id show additional info about language change identified by 'id'\n\
-transition=? list all language changes\n\
-unittest compile in unit tests\n\
-v verbose\n\
-version=level compile in version code >= level\n\
-version=ident compile in version code identified by ident\n\
@@ -414,6 +419,7 @@ int tryMain(size_t argc, char *argv[])
char noboundscheck = 0;
int setdefaultlib = 0;
const char *inifilename = NULL;
global.init();
#ifdef DEBUG
printf("DMD %s DEBUG\n", global.version);
@@ -425,7 +431,7 @@ int tryMain(size_t argc, char *argv[])
if (argc < 1 || !argv)
{
Largs:
error(0, "missing or null command line arguments");
error(Loc(), "missing or null command line arguments");
fatal();
}
for (size_t i = 0; i < argc; i++)
@@ -435,7 +441,7 @@ int tryMain(size_t argc, char *argv[])
}
if (response_expand(&argc,&argv)) // expand response files
error(0, "can't open response file");
error(Loc(), "can't open response file");
files.reserve(argc - 1);
@@ -465,7 +471,9 @@ int tryMain(size_t argc, char *argv[])
#if TARGET_WINDOS
global.params.is64bit = 0;
global.params.defaultlibname = "phobos";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
#elif TARGET_LINUX
global.params.defaultlibname = "libphobos2.a";
#elif TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
global.params.defaultlibname = "phobos2";
#else
#error "fix this"
@@ -552,9 +560,29 @@ int tryMain(size_t argc, char *argv[])
global.params.useDeprecated = 2;
else if (strcmp(p + 1, "c") == 0)
global.params.link = 0;
else if (strcmp(p + 1, "cov") == 0)
global.params.cov = 1;
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
else if (memcmp(p + 1, "cov", 3) == 0)
{
global.params.cov = true;
// Parse:
// -cov
// -cov=nnn
if (p[4] == '=')
{
if (isdigit((unsigned char)p[5]))
{ long percent;
errno = 0;
percent = strtol(p + 5, &p, 10);
if (*p || errno || percent > 100)
goto Lerror;
global.params.covPercent = percent;
}
else
goto Lerror;
}
else if (p[4])
goto Lerror;
}
else if (strcmp(p + 1, "shared") == 0
#if TARGET_OSX
// backwards compatibility with old switch
@@ -562,6 +590,7 @@ int tryMain(size_t argc, char *argv[])
#endif
)
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;
#endif
@@ -578,7 +607,7 @@ int tryMain(size_t argc, char *argv[])
else if (strcmp(p + 1, "gx") == 0)
global.params.stackstomp = true;
else if (strcmp(p + 1, "gt") == 0)
{ error(0, "use -profile instead of -gt");
{ error(Loc(), "use -profile instead of -gt");
global.params.trace = 1;
}
else if (strcmp(p + 1, "m32") == 0)
@@ -592,13 +621,57 @@ int tryMain(size_t argc, char *argv[])
#if DMDV2
else if (strcmp(p + 1, "vtls") == 0)
global.params.vtls = 1;
else if (memcmp(p + 1, "transition", 10) == 0)
{
// Parse:
// -transition=number
if (p[11] == '=')
{
if (strcmp(p + 12, "?") == 0)
{
printf("\
Language changes listed by -transition=id:\n\
=field,3449 do list all non-mutable fields occupies object instance\n\
=tls do list all variables going into thread local storage\n\
");
return EXIT_FAILURE;
}
if (isdigit((unsigned char)p[12]))
{ long num;
errno = 0;
num = strtol(p + 12, &p, 10);
if (*p || errno || num > INT_MAX)
goto Lerror;
switch (num) // Bugzilla issue number
{
case 3449:
global.params.vfield = 1;
break;
default:
goto Lerror;
}
}
else if (Lexer::isValidIdentifier(p + 12))
{
if (strcmp(p + 12, "tls") == 0)
global.params.vtls = 1;
else if (strcmp(p + 12, "field") == 0)
global.params.vfield = 1;
}
else
goto Lerror;
}
else
goto Lerror;
}
#endif
else if (strcmp(p + 1, "v1") == 0)
{
#if DMDV1
global.params.Dversion = 1;
#else
error(0, "use DMD 1.0 series compilers for -v1 switch");
error(Loc(), "use DMD 1.0 series compilers for -v1 switch");
break;
#endif
}
@@ -635,7 +708,7 @@ int tryMain(size_t argc, char *argv[])
break;
case 0:
error(0, "-o no longer supported, use -of or -od");
error(Loc(), "-o no longer supported, use -of or -od");
break;
default:
@@ -826,6 +899,10 @@ int tryMain(size_t argc, char *argv[])
goto Lnoarg;
global.params.moduleDeps = new OutBuffer;
}
else if (strcmp(p + 1, "main") == 0)
{
global.params.addMain = true;
}
else if (memcmp(p + 1, "man", 3) == 0)
{
#if _WIN32
@@ -874,7 +951,7 @@ int tryMain(size_t argc, char *argv[])
if (ext && FileName::equals(ext, "d") == 0
&& FileName::equals(ext, "di") == 0)
{
error(0, "-run must be followed by a source file, not '%s'", argv[i + 1]);
error(Loc(), "-run must be followed by a source file, not '%s'", argv[i + 1]);
break;
}
@@ -891,11 +968,11 @@ int tryMain(size_t argc, char *argv[])
else
{
Lerror:
error(0, "unrecognized switch '%s'", argv[i]);
error(Loc(), "unrecognized switch '%s'", argv[i]);
continue;
Lnoarg:
error(0, "argument expected for switch '%s'", argv[i]);
error(Loc(), "argument expected for switch '%s'", argv[i]);
continue;
}
}
@@ -914,7 +991,7 @@ int tryMain(size_t argc, char *argv[])
}
if(global.params.is64bit != is64bit)
error(0, "the architecture must not be changed in the %s section of %s",
error(Loc(), "the architecture must not be changed in the %s section of %s",
is64bit ? "Environment64" : "Environment32", inifilename);
if (global.errors)
@@ -935,7 +1012,7 @@ int tryMain(size_t argc, char *argv[])
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
if (global.params.lib && global.params.dll)
error(0, "cannot mix -lib and -shared");
error(Loc(), "cannot mix -lib and -shared");
#endif
if (global.params.release)
@@ -997,7 +1074,7 @@ int tryMain(size_t argc, char *argv[])
}
else if (global.params.run)
{
error(0, "flags conflict with -run");
error(Loc(), "flags conflict with -run");
fatal();
}
else
@@ -1057,6 +1134,8 @@ int tryMain(size_t argc, char *argv[])
Type::init();
Id::initialize();
Module::init();
Target::init();
Expression::init();
initPrecedence();
if (global.params.verbose)
@@ -1101,10 +1180,15 @@ int tryMain(size_t argc, char *argv[])
}
}
if (global.params.addMain)
{
files.push(const_cast<char*>(global.main_d)); // a dummy name, we never actually look up this file
}
// Create Modules
Modules modules;
modules.reserve(files.dim);
int firstmodule = 1;
bool firstmodule = true;
for (size_t i = 0; i < files.dim; i++)
{
const char *ext;
@@ -1196,12 +1280,12 @@ int tryMain(size_t argc, char *argv[])
strcmp(name, ".") == 0)
{
Linvalid:
error(0, "invalid file name '%s'", files[i]);
error(Loc(), "invalid file name '%s'", files[i]);
fatal();
}
}
else
{ error(0, "unrecognized file extension %s", ext);
{ error(Loc(), "unrecognized file extension %s", ext);
fatal();
}
}
@@ -1221,11 +1305,30 @@ int tryMain(size_t argc, char *argv[])
if (firstmodule)
{ global.params.objfiles->push((char *)m->objfile->name->str);
firstmodule = 0;
firstmodule = false;
}
}
// Read files
/* Start by "reading" the dummy main.d file
*/
if (global.params.addMain)
{
for (size_t i = 0; 1; i++)
{
assert(i != modules.dim);
Module *m = modules[i];
if (strcmp(m->srcfile->name->str, global.main_d) == 0)
{
static const char buf[] = "int main(){return 0;}";
m->srcfile->setbuffer((void *)buf, sizeof(buf));
m->srcfile->ref = 1;
break;
}
}
}
#define ASYNCREAD 1
#if ASYNCREAD
// Multi threaded
@@ -1261,7 +1364,7 @@ int tryMain(size_t argc, char *argv[])
#if ASYNCREAD
if (aw->read(filei))
{
error(0, "cannot read file %s", m->srcfile->name->toChars());
error(Loc(), "cannot read file %s", m->srcfile->name->toChars());
fatal();
}
#endif
@@ -1296,7 +1399,7 @@ int tryMain(size_t argc, char *argv[])
if (anydocfiles && modules.dim &&
(global.params.oneobj || global.params.objname))
{
error(0, "conflicting Ddoc and obj generation options");
error(Loc(), "conflicting Ddoc and obj generation options");
fatal();
}
if (global.errors)
@@ -1325,7 +1428,7 @@ int tryMain(size_t argc, char *argv[])
m = modules[i];
if (global.params.verbose)
printf("importall %s\n", m->toChars());
m->importAll(0);
m->importAll(NULL);
}
if (global.errors)
fatal();
@@ -1537,7 +1640,7 @@ int tryMain(size_t argc, char *argv[])
if (!global.params.objfiles->dim)
{
if (global.params.link)
error(0, "no object files to link");
error(Loc(), "no object files to link");
}
else
{
@@ -1573,15 +1676,15 @@ int main(int argc, char *argv[])
#if WINDOWS_SEH
__try
{
#endif
status = tryMain(argc, argv);
#if WINDOWS_SEH
}
__except (__ehfilter(GetExceptionInformation()))
{
printf("Stack overflow\n");
fatal();
}
#else
status = tryMain(argc, argv);
#endif
return status;
}
+33 -44
View File
@@ -102,9 +102,6 @@ void unittests();
#define DMDV2 1 // Version 2.0 features
#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN
#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class
#define BUG6652 2 // Making foreach range statement parameter non-ref in default
// 1: Modifying iteratee in body is warned with -w switch
// 2: Modifying iteratee in body is error without -d switch
// Set if C++ mangling is done by the front end
#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || IN_LLVM))
@@ -159,24 +156,27 @@ struct Param
{
bool obj; // write object file
bool link; // perform link
#if !IN_LLVM
#if IN_LLVM
bool verbose; // verbose compile
bool vtls; // identify thread local variables
bool vfield; // identify non-mutable field variables
ubyte symdebug; // insert debug symbolic information
bool is64bit; // generate 64 bit code
#else
char dll; // generate shared dynamic library
char lib; // write library file instead of object file(s)
char multiobj; // break one object file into multiple ones
char oneobj; // write one object file instead of multiple ones
bool trace; // insert profiling hooks
char quiet; // suppress non-error messages
#endif
bool verbose; // verbose compile
bool vtls; // identify thread local variables
ubyte symdebug; // insert debug symbolic information
#if !IN_LLVM
char alwaysframe; // always emit standard stack frame
char optimize; // run optimizer
#endif
char verbose; // verbose compile
char vtls; // identify thread local variables
char vfield; // identify non-mutable field variables
char symdebug; // insert debug symbolic information
bool alwaysframe; // always emit standard stack frame
bool optimize; // run optimizer
char map; // generate linker .map file
bool is64bit; // generate 64 bit code
#if !IN_LLVM
char is64bit; // generate 64 bit code
char isLinux; // generate code for linux
char isOSX; // generate code for Mac OSX
char isWindows; // generate code for Windows
@@ -211,16 +211,21 @@ struct Param
ubyte warnings; // 0: enable warnings
// 1: warnings as errors
// 2: informational warnings (no errors)
#if !IN_LLVM
char pic; // generate position-independent-code for shared libs
char cov; // generate code coverage data
char nofloat; // code should not pull in floating point support
#endif
#if IN_LLVM
ubyte Dversion; // D version number
bool ignoreUnsupportedPragmas; // rather than error on them
bool enforcePropertySyntax;
#if !IN_LLVM
bool addMain; // LDC_FIXME: Implement.
#else
bool pic; // generate position-independent-code for shared libs
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
bool addMain; // add a default main() function
#endif
char *argv0; // program name
@@ -304,6 +309,11 @@ struct Param
#endif
};
struct Compiler
{
const char *vendor; // Compiler backend name
};
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
@@ -328,11 +338,10 @@ struct Global
const char *map_ext; // for .map files
const char *copyright;
const char *written;
const char *main_d; // dummy filename for dummy main()
Strings *path; // Array of char*'s which form the import lookup path
Strings *filePath; // Array of char*'s which form the file import lookup path
structalign_t structalign; // default alignment for struct fields
const char *version;
#if IN_LLVM
char *ldc_version;
@@ -341,6 +350,7 @@ struct Global
bool inExtraInliningSemantic;
#endif
Compiler compiler;
Param params;
unsigned errors; // number of errors reported so far
unsigned warnings; // number of warnings reported so far
@@ -361,7 +371,7 @@ struct Global
*/
bool endGagging(unsigned oldGagged);
Global();
void init();
};
extern Global global;
@@ -417,14 +427,6 @@ typedef d_uns32 d_dchar;
typedef longdouble real_t;
#endif
// Modify OutBuffer::writewchar to write the correct size of wchar
#if _WIN32
#define writewchar writeword
#else
// This needs a configuration test...
#define writewchar write4
#endif
#ifdef IN_GCC
#include "d-gcc-complex_t.h"
#endif
@@ -443,12 +445,6 @@ struct Loc
filename = NULL;
}
Loc(int x)
{
linnum = x;
filename = NULL;
}
Loc(Module *mod, unsigned linnum);
char *toChars();
@@ -534,13 +530,6 @@ void halt();
void util_progress();
#endif
/*** Where to send error messages ***/
#if defined(IN_GCC) || IN_LLVM
#define stdmsg stderr
#else
#define stdmsg stderr
#endif
#if !IN_LLVM
struct Dsymbol;
class Library;
+14 -7
View File
@@ -476,11 +476,11 @@ bool Module::read(Loc loc)
for (size_t i = 0; i < global.path->dim; i++)
{
char *p = (*global.path)[i];
fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p);
fprintf(stderr, "import path[%llu] = %s\n", (ulonglong)i, p);
}
}
else
fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
fprintf(stderr, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
fatal();
}
return false;
@@ -766,7 +766,8 @@ void Module::parse()
p.nextToken();
members = p.parseModule();
::free(srcfile->buffer);
if (srcfile->ref == 0)
::free(srcfile->buffer);
srcfile->buffer = NULL;
srcfile->len = 0;
@@ -804,8 +805,14 @@ void Module::parse()
assert(prev);
Module *mprev = prev->isModule();
if (mprev)
error(loc, "from file %s conflicts with another module %s from file %s",
srcname, mprev->toChars(), mprev->srcfile->toChars());
{
if (strcmp(srcname, mprev->srcfile->toChars()) == 0)
error(loc, "from file %s must be imported as module '%s'",
srcname, toPrettyChars());
else
error(loc, "from file %s conflicts with another module %s from file %s",
srcname, mprev->toChars(), mprev->srcfile->toChars());
}
else
{
Package *pkg = prev->isPackage();
@@ -846,7 +853,7 @@ void Module::importAll(Scope *prevsc)
// would fail inside object.d.
if (members->dim == 0 || ((*members)[0])->ident != Id::object)
{
Import *im = new Import(0, NULL, Id::object, NULL, 0);
Import *im = new Import(Loc(), NULL, Id::object, NULL, 0);
members->shift(im);
}
@@ -1113,7 +1120,7 @@ Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
Dsymbol *Module::symtabInsert(Dsymbol *s)
{
searchCacheIdent = 0; // symbol is inserted, so invalidate cache
searchCacheIdent = NULL; // symbol is inserted, so invalidate cache
return Package::symtabInsert(s);
}
+839 -1011
View File
File diff suppressed because it is too large Load Diff
+89 -77
View File
@@ -121,17 +121,18 @@ extern int Tsize_t;
extern int Tptrdiff_t;
/* pick this order of numbers so switch statements work better
*/
#define MODconst 1 // type is const
#define MODimmutable 4 // type is immutable
#define MODshared 2 // type is shared
#define MODwild 8 // type is wild
#define MODmutable 0x10 // type is mutable (only used in wildcard matching)
struct Type : Object
{
TY ty;
unsigned char mod; // modifiers MODxxxx
/* pick this order of numbers so switch statements work better
*/
#define MODconst 1 // type is const
#define MODimmutable 4 // type is immutable
#define MODshared 2 // type is shared
#define MODwild 8 // type is wild
#define MODmutable 0x10 // type is mutable (only used in wildcard matching)
char *deco;
/* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc.
@@ -157,49 +158,47 @@ struct Type : Object
type *ctype; // for back end
#endif
#define tvoid basic[Tvoid]
#define tint8 basic[Tint8]
#define tuns8 basic[Tuns8]
#define tint16 basic[Tint16]
#define tuns16 basic[Tuns16]
#define tint32 basic[Tint32]
#define tuns32 basic[Tuns32]
#define tint64 basic[Tint64]
#define tuns64 basic[Tuns64]
#define tint128 basic[Tint128]
#define tuns128 basic[Tuns128]
#define tfloat32 basic[Tfloat32]
#define tfloat64 basic[Tfloat64]
#define tfloat80 basic[Tfloat80]
static Type *tvoid;
static Type *tint8;
static Type *tuns8;
static Type *tint16;
static Type *tuns16;
static Type *tint32;
static Type *tuns32;
static Type *tint64;
static Type *tuns64;
static Type *tint128;
static Type *tuns128;
static Type *tfloat32;
static Type *tfloat64;
static Type *tfloat80;
#define timaginary32 basic[Timaginary32]
#define timaginary64 basic[Timaginary64]
#define timaginary80 basic[Timaginary80]
static Type *timaginary32;
static Type *timaginary64;
static Type *timaginary80;
#define tcomplex32 basic[Tcomplex32]
#define tcomplex64 basic[Tcomplex64]
#define tcomplex80 basic[Tcomplex80]
static Type *tcomplex32;
static Type *tcomplex64;
static Type *tcomplex80;
#define tbool basic[Tbool]
#define tchar basic[Tchar]
#define twchar basic[Twchar]
#define tdchar basic[Tdchar]
static Type *tbool;
static Type *tchar;
static Type *twchar;
static Type *tdchar;
// Some special types
#define tshiftcnt tint32 // right side of shift expression
// #define tboolean tint32 // result of boolean expression
#define tboolean tbool // result of boolean expression
#define tindex tsize_t // array/ptr index
static Type *tshiftcnt;
static Type *tboolean;
static Type *tvoidptr; // void*
static Type *tstring; // immutable(char)[]
static Type *tvalist; // va_list alias
#define terror basic[Terror] // for error recovery
static Type *terror; // for error recovery
static Type *tnull; // for null type
#define tnull basic[Tnull] // for null type
#define tsize_t basic[Tsize_t] // matches size_t alias
#define tptrdiff_t basic[Tptrdiff_t] // matches ptrdiff_t alias
#define thash_t tsize_t // matches hash_t alias
static Type *tsize_t; // matches size_t alias
static Type *tptrdiff_t; // matches ptrdiff_t alias
static Type *thash_t; // matches hash_t alias
static Type *tindex; // array/ptr index
static ClassDeclaration *typeinfo;
static ClassDeclaration *typeinfoclass;
@@ -253,6 +252,8 @@ struct Type : Object
#else
static void init();
#endif
#define SIZE_INVALID (~(d_uns64)0)
d_uns64 size();
virtual d_uns64 size(Loc loc);
virtual unsigned alignsize();
@@ -267,7 +268,6 @@ struct Type : Object
void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
void modToBuffer(OutBuffer *buf);
char *modToChars();
void toJsonProperty(JsonOut *json, const char *);
virtual void toJson(JsonOut *json);
#if CPP_MANGLE
virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
@@ -292,6 +292,7 @@ struct Type : Object
int isWild() { return mod & MODwild; }
int isSharedWild() { return mod == (MODshared | MODwild); }
int isNaked() { return mod == 0; }
Type *nullAttributes();
Type *constOf();
Type *invariantOf();
Type *mutableOf();
@@ -310,6 +311,7 @@ struct Type : Object
Type *referenceTo();
Type *arrayOf();
Type *aliasthisOf();
int checkAliasThisRec();
virtual Type *makeConst();
virtual Type *makeInvariant();
virtual Type *makeShared();
@@ -326,14 +328,14 @@ struct Type : Object
Type *substWildTo(unsigned mod);
virtual Type *toHeadMutable();
virtual ClassDeclaration *isClassHandle();
virtual Expression *getProperty(Loc loc, Identifier *ident);
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
virtual Expression *getProperty(Loc loc, Identifier *ident, int flag);
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
virtual structalign_t alignment();
Expression *noMember(Scope *sc, Expression *e, Identifier *ident);
virtual Expression *defaultInit(Loc loc = 0);
Expression *noMember(Scope *sc, Expression *e, Identifier *ident, int flag);
virtual Expression *defaultInit(Loc loc = Loc());
virtual Expression *defaultInitLiteral(Loc loc);
virtual Expression *voidInitLiteral(VarDeclaration *var);
virtual int isZeroInit(Loc loc = 0); // if initializer is 0
virtual int isZeroInit(Loc loc = Loc()); // if initializer is 0
#if IN_DMD
virtual dt_t **toDt(dt_t **pdt);
#endif
@@ -383,8 +385,8 @@ struct TypeError : Type
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
d_uns64 size(Loc loc);
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident, int flag);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
TypeTuple *toArgTypes();
@@ -425,8 +427,8 @@ struct TypeBasic : Type
#if IN_LLVM
unsigned alignment();
#endif
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident, int flag);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
char *toChars();
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
#if CPP_MANGLE
@@ -459,8 +461,8 @@ struct TypeVector : Type
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
unsigned alignsize();
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident, int flag);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
char *toChars();
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
#if IN_LLVM
@@ -493,7 +495,7 @@ struct TypeVector : Type
struct TypeArray : TypeNext
{
TypeArray(TY ty, Type *next);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
};
// Static array, one with a fixed dimension
@@ -511,7 +513,7 @@ struct TypeSArray : TypeArray
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
int isString();
int isZeroInit(Loc loc);
structalign_t alignment();
@@ -554,7 +556,7 @@ struct TypeDArray : TypeArray
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
int isString();
int isZeroInit(Loc loc);
int checkBoolean();
@@ -592,7 +594,7 @@ struct TypeAArray : TypeArray
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
Expression *defaultInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
int isZeroInit(Loc loc);
@@ -651,7 +653,7 @@ struct TypeReference : TypeNext
d_uns64 size(Loc loc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
#if CPP_MANGLE
@@ -706,7 +708,6 @@ struct TypeFunction : TypeNext
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
bool hasMutableIndirectionParams();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
@@ -723,7 +724,7 @@ struct TypeFunction : TypeNext
bool parameterEscapes(Parameter *p);
Type *addStorageClass(StorageClass stc);
MATCH callMatch(Expression *ethis, Expressions *toargs, int flag = 0);
MATCH callMatch(Type *tthis, Expressions *toargs, int flag = 0);
#if IN_DMD
type *toCtype();
#endif
@@ -761,7 +762,7 @@ struct TypeDelegate : TypeNext
int isZeroInit(Loc loc);
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
int hasPointers();
TypeTuple *toArgTypes();
#if CPP_MANGLE
@@ -776,11 +777,13 @@ struct TypeDelegate : TypeNext
struct TypeQualified : Type
{
Loc loc;
Identifiers idents; // array of Identifier's representing ident.ident.ident etc.
Objects idents; // array of Identifier and TypeInstance,
// representing ident.ident!tiargs.ident. ... etc.
TypeQualified(TY ty, Loc loc);
void syntaxCopyHelper(TypeQualified *t);
void addIdent(Identifier *ident);
void addInst(TemplateInstance *inst);
void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
void toJson(JsonOut *json);
d_uns64 size(Loc loc);
@@ -826,6 +829,7 @@ struct TypeInstance : TypeQualified
Dsymbol *toDsymbol(Scope *sc);
Type *reliesOnTident(TemplateParameters *tparams = NULL);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
Expression *toExpression();
};
struct TypeTypeof : TypeQualified
@@ -839,6 +843,7 @@ 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);
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
};
@@ -849,14 +854,26 @@ struct TypeReturn : TypeQualified
const char *kind();
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
};
// Whether alias this dependency is recursive or not.
enum AliasThisRec
{
RECno = 0, // no alias this recursion
RECyes = 1, // alias this has recursive dependency
RECfwdref = 2, // not yet known
RECtracing = 0x4, // mark in progress of implicitConvTo/wildConvTo
};
struct TypeStruct : Type
{
StructDeclaration *sym;
enum AliasThisRec att;
TypeStruct(StructDeclaration *sym);
const char *kind();
@@ -869,7 +886,7 @@ struct TypeStruct : Type
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
structalign_t alignment();
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
@@ -919,8 +936,8 @@ struct TypeEnum : Type
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
Expression *getProperty(Loc loc, Identifier *ident, int flag);
int isintegral();
int isfloating();
int isreal();
@@ -965,9 +982,9 @@ struct TypeTypedef : Type
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
structalign_t alignment();
Expression *getProperty(Loc loc, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident, int flag);
int isintegral();
int isfloating();
int isreal();
@@ -1007,6 +1024,7 @@ struct TypeTypedef : Type
struct TypeClass : Type
{
ClassDeclaration *sym;
enum AliasThisRec att;
TypeClass(ClassDeclaration *sym);
const char *kind();
@@ -1018,7 +1036,7 @@ struct TypeClass : Type
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toJson(JsonOut *json);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag);
ClassDeclaration *isClassHandle();
int isBaseOf(Type *t, int *poffset);
MATCH implicitConvTo(Type *to);
@@ -1066,7 +1084,7 @@ struct TypeTuple : Type
void toDecoBuffer(OutBuffer *buf, int flag);
#endif
void toJson(JsonOut *json);
Expression *getProperty(Loc loc, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident, int flag);
Expression *defaultInit(Loc loc);
TypeInfoDeclaration *getTypeInfoDeclaration();
};
@@ -1099,10 +1117,7 @@ struct TypeNull : Type
void toJson(JsonOut *json);
d_uns64 size(Loc loc);
//Expression *getProperty(Loc loc, Identifier *ident);
//Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
//Expression *defaultInitLiteral(Loc loc);
};
/**************************************************************/
@@ -1122,10 +1137,11 @@ struct Parameter : Object
Type *isLazyArray();
void toDecoBuffer(OutBuffer *buf, bool mangle);
int dyncast() { return DYNCAST_PARAMETER; } // kludge for template.isType()
void toJson(JsonOut *json);
static Parameters *arraySyntaxCopy(Parameters *args);
static char *argsTypesToChars(Parameters *args, int varargs);
#if CPP_MANGLE
static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs);
#endif
static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Parameters *arguments, int varargs);
static void argsToDecoBuffer(OutBuffer *buf, Parameters *arguments, bool mangle);
static int isTPL(Parameters *arguments);
@@ -1136,10 +1152,6 @@ struct Parameter : Object
static int foreach(Parameters *args, ForeachDg dg, void *ctx, size_t *pn=NULL);
};
extern int PTRSIZE;
extern int REALSIZE;
extern int REALPAD;
extern int REALALIGNSIZE;
extern int Tsize_t;
extern int Tptrdiff_t;
+161 -94
View File
@@ -39,7 +39,7 @@
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, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
static void templateResolve(Match *m, TemplateDeclaration *td, Loc loc, Scope *sc, Objects *tiargs, Expression *ethis, Expressions *arguments);
/******************************** Expression **************************/
@@ -202,11 +202,11 @@ Objects *opToArg(Scope *sc, enum TOK op)
case TOKcatass: op = TOKcat; break;
case TOKpowass: op = TOKpow; break;
}
Expression *e = new StringExp(0, (char *)Token::toChars(op));
Expression *e = new StringExp(Loc(), (char *)Token::toChars(op));
e = e->semantic(sc);
Objects *targsi = new Objects();
targsi->push(e);
return targsi;
Objects *tiargs = new Objects();
tiargs->push(e);
return tiargs;
}
/************************************
@@ -237,26 +237,29 @@ Expression *UnaExp::op_overload(Scope *sc)
if (fd)
{
ae = resolveOpDollar(sc, ae);
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi);
Objects *tiargs = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, tiargs);
e = new CallExp(loc, e, ae->arguments);
e = e->semantic(sc);
return e;
}
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
if (ad->aliasthis && ae->e1->type != att1)
{
/* Rewrite op(a[arguments]) as:
* op(a.aliasthis[arguments])
*/
Expression *e1 = ae->copy();
((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
UnaExp *ue = (UnaExp *)copy();
if (!ue->att1 && ae->e1->type->checkAliasThisRec())
ue->att1 = ae->e1->type;
ue->e1 = e1;
if (Expression *e = ue->trySemantic(sc))
return e;
}
att1 = NULL;
}
}
else if (e1->op == TOKslice)
@@ -281,26 +284,29 @@ Expression *UnaExp::op_overload(Scope *sc)
{ a->push(se->lwr);
a->push(se->upr);
}
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, targsi);
Objects *tiargs = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, tiargs);
e = new CallExp(loc, e, a);
e = e->semantic(sc);
return e;
}
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
if (ad->aliasthis && se->e1->type != att1)
{
/* Rewrite op(a[lwr..upr]) as:
* op(a.aliasthis[lwr..upr])
*/
Expression *e1 = se->copy();
((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
UnaExp *ue = (UnaExp *)copy();
if (!ue->att1 && se->e1->type->checkAliasThisRec())
ue->att1 = se->e1->type;
ue->e1 = e1;
if (Expression *e = ue->trySemantic(sc))
return e;
}
att1 = NULL;
}
}
#endif
@@ -344,24 +350,26 @@ Expression *UnaExp::op_overload(Scope *sc)
fd = search_function(ad, Id::opUnary);
if (fd)
{
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, targsi);
Objects *tiargs = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, tiargs);
e = new CallExp(loc, e);
e = e->semantic(sc);
return e;
}
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
if (ad->aliasthis && this->e1->type != att1)
{
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
//printf("att una %s e1 = %s\n", Token::toChars(op), this->e1->type->toChars());
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
UnaExp *ue = (UnaExp *)copy();
if (!ue->att1 && this->e1->type->checkAliasThisRec())
ue->att1 = this->e1->type;
ue->e1 = e1;
return ue->trySemantic(sc);
}
#endif
}
@@ -388,16 +396,18 @@ Expression *ArrayExp::op_overload(Scope *sc)
}
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
if (ad->aliasthis && this->e1->type != att1)
{
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
//printf("att arr e1 = %s\n", this->e1->type->toChars());
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
UnaExp *ue = (UnaExp *)copy();
if (!ue->att1 && this->e1->type->checkAliasThisRec())
ue->att1 = this->e1->type;
ue->e1 = e1;
return ue->trySemantic(sc);
}
}
return NULL;
@@ -426,9 +436,9 @@ Expression *CastExp::op_overload(Scope *sc)
return build_overload(loc, sc, e1, NULL, fd);
}
#endif
Objects *targsi = new Objects();
targsi->push(to);
Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, targsi);
Objects *tiargs = new Objects();
tiargs->push(to);
Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, tiargs);
e = new CallExp(loc, e);
e = e->semantic(sc);
return e;
@@ -487,7 +497,7 @@ Expression *BinExp::op_overload(Scope *sc)
}
#endif
Objects *targsi = NULL;
Objects *tiargs = NULL;
#if DMDV2
if (op == TOKplusplus || op == TOKminusminus)
{ // Bug4099 fix
@@ -500,16 +510,28 @@ Expression *BinExp::op_overload(Scope *sc)
/* Try the new D2 scheme, opBinary and opBinaryRight
*/
if (ad1)
{
s = search_function(ad1, Id::opBinary);
if (s && !s->isTemplateDeclaration())
{ e1->error("%s.opBinary isn't a template", e1->toChars());
return new ErrorExp();
}
}
if (ad2)
{
s_r = search_function(ad2, Id::opBinaryRight);
if (s_r && !s_r->isTemplateDeclaration())
{ e2->error("%s.opBinaryRight isn't a template", e2->toChars());
return new ErrorExp();
}
}
// Set targsi, the template argument list, which will be the operator string
// Set tiargs, the template argument list, which will be the operator string
if (s || s_r)
{
id = Id::opBinary;
id_r = Id::opBinaryRight;
targsi = opToArg(sc, op);
tiargs = opToArg(sc, op);
}
}
#endif
@@ -541,7 +563,7 @@ Expression *BinExp::op_overload(Scope *sc)
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
}
}
@@ -556,7 +578,7 @@ Expression *BinExp::op_overload(Scope *sc)
}
else
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, e2, &args1);
templateResolve(&m, td, loc, sc, tiargs, e2, &args1);
}
}
@@ -571,7 +593,7 @@ Expression *BinExp::op_overload(Scope *sc)
else if (m.last == MATCHnomatch)
{
m.lastf = m.anyf;
if (targsi)
if (tiargs)
goto L1;
}
@@ -593,7 +615,7 @@ Expression *BinExp::op_overload(Scope *sc)
L1:
#if 1 // Retained for D1 compatibility
if (isCommutative() && !targsi)
if (isCommutative() && !tiargs)
{
s = NULL;
s_r = NULL;
@@ -634,7 +656,7 @@ L1:
}
else
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
}
}
FuncDeclaration *lastf = m.lastf;
@@ -648,7 +670,7 @@ L1:
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, e2, &args1);
templateResolve(&m, td, loc, sc, tiargs, e2, &args1);
}
}
@@ -709,11 +731,15 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
*/
if (att1 && this->e1->type == att1)
return NULL;
//printf("att bin e1 = %s\n", this->e1->type->toChars());
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att1 && this->e1->type->checkAliasThisRec())
be->att1 = this->e1->type;
be->e1 = e1;
return be->trySemantic(sc);
}
// Try alias this on second operand
@@ -726,11 +752,15 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
if (att2 && this->e2->type == att2)
return NULL;
//printf("att bin e2 = %s\n", this->e2->type->toChars());
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att2 && this->e2->type->checkAliasThisRec())
be->att2 = this->e2->type;
be->e2 = e2;
return be->trySemantic(sc);
}
#endif
return NULL;
@@ -760,7 +790,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
s_r = NULL;
}
Objects *targsi = NULL;
Objects *tiargs = NULL;
if (s || s_r)
{
@@ -797,7 +827,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
}
}
@@ -813,7 +843,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
}
else
{ TemplateDeclaration *td = s_r->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, e2, &args1);
templateResolve(&m, td, loc, sc, tiargs, e2, &args1);
}
}
@@ -882,11 +912,15 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
*/
if (att1 && this->e1->type == att1)
return NULL;
//printf("att cmp_bin e1 = %s\n", this->e1->type->toChars());
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att1 && this->e1->type->checkAliasThisRec())
be->att1 = this->e1->type;
be->e1 = e1;
return be->trySemantic(sc);
}
// Try alias this on second operand
@@ -895,11 +929,15 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
if (att2 && this->e2->type == att2)
return NULL;
//printf("att cmp_bin e2 = %s\n", this->e2->type->toChars());
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att2 && this->e2->type->checkAliasThisRec())
be->att2 = this->e2->type;
be->e2 = e2;
return be->trySemantic(sc);
}
return NULL;
@@ -979,26 +1017,29 @@ Expression *BinAssignExp::op_overload(Scope *sc)
Expressions *a = (Expressions *)ae->arguments->copy();
a->insert(0, e2);
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi);
Objects *tiargs = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, tiargs);
e = new CallExp(loc, e, a);
e = e->semantic(sc);
return e;
}
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
if (ad->aliasthis && ae->e1->type != att1)
{
/* Rewrite a[arguments] op= e2 as:
* a.aliasthis[arguments] op= e2
*/
Expression *e1 = ae->copy();
((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att1 && ae->e1->type->checkAliasThisRec())
be->att1 = ae->e1->type;
be->e1 = e1;
if (Expression *e = be->trySemantic(sc))
return e;
}
att1 = NULL;
}
}
else if (e1->op == TOKslice)
@@ -1025,26 +1066,29 @@ Expression *BinAssignExp::op_overload(Scope *sc)
a->push(se->upr);
}
Objects *targsi = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, targsi);
Objects *tiargs = opToArg(sc, op);
Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, tiargs);
e = new CallExp(loc, e, a);
e = e->semantic(sc);
return e;
}
// Didn't find it. Forward to aliasthis
if (ad->aliasthis)
if (ad->aliasthis && se->e1->type != att1)
{
/* Rewrite a[lwr..upr] op= e2 as:
* a.aliasthis[lwr..upr] op= e2
*/
Expression *e1 = se->copy();
((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att1 && se->e1->type->checkAliasThisRec())
be->att1 = se->e1->type;
be->e1 = e1;
if (Expression *e = be->trySemantic(sc))
return e;
}
att1 = NULL;
}
}
#endif
@@ -1072,19 +1116,25 @@ Expression *BinAssignExp::op_overload(Scope *sc)
}
#endif
Objects *targsi = NULL;
Objects *tiargs = NULL;
#if DMDV2
if (!s)
{ /* Try the new D2 scheme, opOpAssign
*/
if (ad1)
{
s = search_function(ad1, Id::opOpAssign);
if (s && !s->isTemplateDeclaration())
{ error("%s.opOpAssign isn't a template", e1->toChars());
return new ErrorExp();
}
}
// Set targsi, the template argument list, which will be the operator string
// Set tiargs, the template argument list, which will be the operator string
if (s)
{
id = Id::opOpAssign;
targsi = opToArg(sc, op);
tiargs = opToArg(sc, op);
}
}
#endif
@@ -1111,7 +1161,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
}
else
{ TemplateDeclaration *td = s->isTemplateDeclaration();
templateResolve(&m, td, sc, loc, targsi, e1, &args2);
templateResolve(&m, td, loc, sc, tiargs, e1, &args2);
}
}
@@ -1126,7 +1176,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
else if (m.last == MATCHnomatch)
{
m.lastf = m.anyf;
if (targsi)
if (tiargs)
goto L1;
}
@@ -1143,11 +1193,15 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
*/
if (att1 && this->e1->type == att1)
return NULL;
//printf("att %s e1 = %s\n", Token::toChars(op), this->e1->type->toChars());
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att1 && this->e1->type->checkAliasThisRec())
be->att1 = this->e1->type;
be->e1 = e1;
return be->trySemantic(sc);
}
// Try alias this on second operand
@@ -1157,11 +1211,15 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
if (att2 && this->e2->type == att2)
return NULL;
//printf("att %s e2 = %s\n", Token::toChars(op), this->e2->type->toChars());
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->trySemantic(sc);
return e;
BinExp *be = (BinExp *)copy();
if (!be->att2 && this->e2->type->checkAliasThisRec())
be->att2 = this->e2->type;
be->e2 = e2;
return be->trySemantic(sc);
}
#endif
return NULL;
@@ -1201,7 +1259,7 @@ Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
FuncDeclaration *fd;
TemplateDeclaration *td;
s = ad->search(0, funcid, 0);
s = ad->search(Loc(), funcid, 0);
if (s)
{ Dsymbol *s2;
@@ -1228,6 +1286,8 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
int sliced = 0;
#endif
Type *tab;
Type *att = NULL;
Expression *org_aggr = aggr;
AggregateDeclaration *ad;
while (1)
@@ -1239,6 +1299,10 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
goto Lerr;
tab = aggr->type->toBasetype();
if (att == tab)
{ aggr = org_aggr;
goto Lerr;
}
switch (tab->ty)
{
case Tarray:
@@ -1277,13 +1341,15 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
}
}
if (Dsymbol *shead = ad->search(0, idfront, 0))
if (Dsymbol *shead = ad->search(Loc(), idfront, 0))
{ // range aggregate
break;
}
if (ad->aliasthis)
{
if (!att && tab->checkAliasThisRec())
att = tab;
aggr = new DotIdExp(aggr->loc, aggr, ad->aliasthis->ident);
continue;
}
@@ -1436,7 +1502,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
/* Look for a front() or back() overload
*/
Identifier *id = (op == TOKforeach) ? Id::Ffront : Id::Fback;
Dsymbol *s = ad->search(0, id, 0);
Dsymbol *s = ad->search(Loc(), id, 0);
FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
if (fd)
{
@@ -1614,12 +1680,13 @@ void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments)
/**************************************
*/
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments)
static void templateResolve(Match *m, TemplateDeclaration *td, Loc loc, Scope *sc,
Objects *tiargs, Expression *ethis, Expressions *arguments)
{
FuncDeclaration *fd;
assert(td);
fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments, 1);
fd = td->deduceFunctionTemplate(loc, sc, tiargs, ethis->type, arguments, 1);
if (!fd)
return;
m->anyf = fd;
+59 -53
View File
@@ -23,7 +23,7 @@
#include "declaration.h"
#include "aggregate.h"
#include "init.h"
#include "enum.h"
#ifdef IN_GCC
#include "d-gcc-real.h"
@@ -68,7 +68,7 @@ Expression *expandVar(int result, VarDeclaration *v)
v->error("recursive initialization of constant");
goto L1;
}
Expression *ei = v->init->toExpression();
Expression *ei = v->getConstInitializer();
if (!ei)
{ if (v->storage_class & STCmanifest)
v->error("enum cannot be initialized with %s", v->init->toChars());
@@ -91,24 +91,20 @@ Expression *expandVar(int result, VarDeclaration *v)
}
else if (ei->implicitConvTo(v->type) >= MATCHconst)
{ // const var initialized with non-const expression
ei = ei->implicitCastTo(0, v->type);
ei = ei->semantic(0);
ei = ei->implicitCastTo(NULL, v->type);
ei = ei->semantic(NULL);
}
else
goto L1;
}
if (v->scope)
else if (!(result & WANTinterpret) &&
!(v->storage_class & STCmanifest) &&
ei->isConst() != 1 && ei->op != TOKstring &&
ei->op != TOKaddress)
{
v->inuse++;
e = ei->syntaxCopy();
e = e->semantic(v->scope);
e = e->implicitCastTo(v->scope, v->type);
// enabling this line causes test22 in test suite to fail
//ei->type = e->type;
v->scope = NULL;
v->inuse--;
goto L1;
}
else if (!ei->type)
if (!ei->type)
{
goto L1;
}
@@ -177,6 +173,7 @@ Expression *fromConstInitializer(int result, Expression *e1)
!(v->storage_class & STCtemplateparameter))
{
e1->error("variable %s cannot be read at compile time", v->toChars());
e = e->copy();
e->type = Type::terror;
}
}
@@ -193,14 +190,22 @@ Expression *Expression::optimize(int result, bool keepLvalue)
Expression *VarExp::optimize(int result, bool keepLvalue)
{
return keepLvalue ? this : fromConstInitializer(result, this);
if (keepLvalue)
{
VarDeclaration *v = var->isVarDeclaration();
if (v && !(v->storage_class & STCmanifest))
return this;
}
return fromConstInitializer(result, this);
}
Expression *TupleExp::optimize(int result, bool keepLvalue)
{
if (e0)
e0 = e0->optimize(WANTvalue | (result & WANTinterpret));
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (*exps)[i];
{
Expression *e = (*exps)[i];
e = e->optimize(WANTvalue | (result & WANTinterpret));
(*exps)[i] = e;
}
@@ -239,6 +244,9 @@ Expression *AssocArrayLiteralExp::optimize(int result, bool keepLvalue)
Expression *StructLiteralExp::optimize(int result, bool keepLvalue)
{
if(stageflags & stageOptimize) return this;
int old = stageflags;
stageflags |= stageOptimize;
if (elements)
{
for (size_t i = 0; i < elements->dim; i++)
@@ -249,6 +257,7 @@ Expression *StructLiteralExp::optimize(int result, bool keepLvalue)
(*elements)[i] = e;
}
}
stageflags = old;
return this;
}
@@ -316,6 +325,14 @@ Expression *BoolExp::optimize(int result, bool keepLvalue)
return e;
}
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;
}
Expression *AddrExp::optimize(int result, bool keepLvalue)
{ Expression *e;
@@ -332,13 +349,8 @@ Expression *AddrExp::optimize(int result, bool keepLvalue)
return e->optimize(result);
}
if (e1->op == TOKvar)
{ VarExp *ve = (VarExp *)e1;
if (ve->var->storage_class & STCmanifest)
e1 = e1->optimize(result);
}
else
e1 = e1->optimize(result);
// Keep lvalue-ness
e1 = e1->optimize(result, true);
// Convert &*ex to ex
if (e1->op == TOKstar)
@@ -489,7 +501,13 @@ Expression *NewExp::optimize(int result, bool keepLvalue)
}
if (result & WANTinterpret)
{
error("cannot evaluate %s at compile time", toChars());
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;
}
@@ -509,12 +527,8 @@ Expression *CallExp::optimize(int result, bool keepLvalue)
size_t pdim = Parameter::dim(tf->parameters) - (tf->varargs == 2 ? 1 : 0);
for (size_t i = 0; i < arguments->dim; i++)
{
bool keepLvalue = false;
if (i < pdim)
{
Parameter *p = Parameter::getNth(tf->parameters, i);
keepLvalue = ((p->storageClass & (STCref | STCout)) != 0);
}
Parameter *p = Parameter::getNth(tf->parameters, i);
bool keepLvalue = (p ? (p->storageClass & (STCref | STCout)) != 0 : false);
Expression *e = (*arguments)[i];
e = e->optimize(WANTvalue, keepLvalue);
(*arguments)[i] = e;
@@ -603,7 +617,7 @@ Expression *CastExp::optimize(int result, bool keepLvalue)
if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
(type->ty == Tpointer || type->ty == Tarray) &&
e1->type->nextOf()->size() == type->nextOf()->size()
e1->type->toBasetype()->nextOf()->size() == type->nextOf()->size()
)
{
Expression *e = e1->castTo(NULL, type);
@@ -801,19 +815,19 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E
Expression *ShlExp::optimize(int result, bool keepLvalue)
{
//printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
return shift_optimize(result, this, Shl);
return shift_optimize(result, this, &Shl);
}
Expression *ShrExp::optimize(int result, bool keepLvalue)
{
//printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
return shift_optimize(result, this, Shr);
return shift_optimize(result, this, &Shr);
}
Expression *UshrExp::optimize(int result, bool keepLvalue)
{
//printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
return shift_optimize(result, this, Ushr);
return shift_optimize(result, this, &Ushr);
}
Expression *AndExp::optimize(int result, bool keepLvalue)
@@ -984,7 +998,8 @@ Expression *IdentityExp::optimize(int result, bool keepLvalue)
Expression *e = this;
if ((this->e1->isConst() && this->e2->isConst()) ||
(this->e1->op == TOKnull && this->e2->op == TOKnull))
(this->e1->op == TOKnull && this->e2->op == TOKnull) ||
(result & WANTinterpret))
{
e = Identity(op, type, this->e1, this->e2);
if (e == EXP_CANT_INTERPRET)
@@ -1017,8 +1032,8 @@ void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr)
return; // we don't know the length yet
}
Expression *dollar = new IntegerExp(0, len, Type::tsize_t);
lengthVar->init = new ExpInitializer(0, dollar);
Expression *dollar = new IntegerExp(Loc(), len, Type::tsize_t);
lengthVar->init = new ExpInitializer(Loc(), dollar);
lengthVar->storage_class |= STCstatic | STCconst;
}
@@ -1027,25 +1042,16 @@ Expression *IndexExp::optimize(int result, bool keepLvalue)
{ Expression *e;
//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
Expression *e1 = this->e1->optimize(
WANTvalue | (result & (WANTinterpret| WANTexpand)));
e1 = fromConstInitializer(result, e1);
if (this->e1->op == TOKvar)
{ VarExp *ve = (VarExp *)this->e1;
if (ve->var->storage_class & STCmanifest)
{ /* We generally don't want to have more than one copy of an
* array literal, but if it's an enum we have to because the
* enum isn't stored elsewhere. See Bugzilla 2559
*/
this->e1 = e1;
}
}
e1 = e1->optimize(WANTvalue | (result & (WANTinterpret| WANTexpand)));
Expression *ex = fromConstInitializer(result, e1);
// We might know $ now
setLengthVarIfKnown(lengthVar, e1);
setLengthVarIfKnown(lengthVar, ex);
e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
if (keepLvalue)
return this;
e = Index(type, e1, e2);
e = Index(type, ex, e2);
if (e == EXP_CANT_INTERPRET)
e = this;
return e;
+298 -151
View File
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -71,9 +71,9 @@ struct Parser : Lexer
Parser(Module *module, unsigned char *base, size_t length, int doDocComment);
Dsymbols *parseModule();
Dsymbols *parseDeclDefs(int once);
Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL);
Dsymbols *parseAutoDeclarations(StorageClass storageClass, unsigned char *comment);
Dsymbols *parseBlock();
Dsymbols *parseBlock(Dsymbol **pLastDecl);
void composeStorageClass(StorageClass stc);
StorageClass parseAttribute(Expressions **pexps);
StorageClass parsePostfix();
@@ -114,7 +114,8 @@ struct Parser : Lexer
Dsymbols *parseDeclarations(StorageClass storage_class, unsigned char *comment);
void parseContracts(FuncDeclaration *f);
void checkDanglingElse(Loc elseloc);
Statement *parseStatement(int flags);
/** endPtr used for documented unittests */
Statement *parseStatement(int flags, unsigned char** endPtr = NULL);
Initializer *parseInitializer();
Expression *parseDefaultInitExp();
void check(Loc loc, enum TOK value);
@@ -123,7 +124,7 @@ struct Parser : Lexer
void checkParens(enum TOK value, Expression *e);
int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt);
int isBasicType(Token **pt);
int isDeclarator(Token **pt, int *haveId, enum TOK endtok);
int isDeclarator(Token **pt, int *haveId, int *haveTpl, enum TOK endtok);
int isParameters(Token **pt);
int isExpression(Token **pt);
int skipParens(Token *t, Token **pt);
+19 -2
View File
@@ -51,14 +51,15 @@ bool initFPU()
int old_cw = _control87(_MCW_EM | _PC_64 | _RC_NEAR,
_MCW_EM | _MCW_PC | _MCW_RC);
#endif
_set_output_format(_TWO_DIGIT_EXPONENT);
return true;
}
static bool doInitFPU = initFPU();
#ifndef _WIN64
extern "C"
{
#ifndef _WIN64
double ld_read(const longdouble* pthis)
{
double res;
@@ -70,6 +71,8 @@ double ld_read(const longdouble* pthis)
}
return res;
}
#endif // !_WIN64
long long ld_readll(const longdouble* pthis)
{
#if 1
@@ -126,6 +129,7 @@ unsigned long long ld_readull(const longdouble* pthis)
#endif
}
#ifndef _WIN64
void ld_set(longdouble* pthis, double d)
{
__asm
@@ -157,9 +161,9 @@ void ld_setull(longdouble* pthis, unsigned long long d)
fstp tbyte ptr [eax]
}
}
#endif // !_WIN64
} // extern "C"
#endif // !_WIN64
longdouble ldexpl(longdouble ld, int exp)
{
@@ -519,6 +523,13 @@ size_t ld_sprint(char* str, int fmt, longdouble x)
// fmt is 'a','A','f' or 'g'
if(fmt != 'a' && fmt != 'A')
{
if (ldouble((unsigned long long)x) == x)
{ // ((1.5 -> 1 -> 1.0) == 1.5) is false
// ((1.0 -> 1 -> 1.0) == 1.0) is true
// see http://en.cppreference.com/w/cpp/io/c/fprintf
char format[] = {'%', '#', 'L', fmt, 0};
return sprintf(str, format, ld_read(&x));
}
char format[] = { '%', fmt, 0 };
return sprintf(str, format, ld_read(&x));
}
@@ -580,6 +591,12 @@ static bool unittest()
ld_sprint(buffer, 'a', ld_pi);
assert(strcmp(buffer, "0x1.921fb54442d1846ap+1") == 0);
ld_sprint(buffer, 'g', ldouble(2.0));
assert(strcmp(buffer, "2.00000") == 0);
ld_sprint(buffer, 'g', ldouble(1234567.89));
assert(strcmp(buffer, "1.23457e+06") == 0);
longdouble ldb = ldouble(0.4);
long long b = ldb;
assert(b == 0);
+14 -3
View File
@@ -42,9 +42,20 @@ typedef volatile long double volatile_longdouble;
inline size_t ld_sprint(char* str, int fmt, longdouble x)
{
char sfmt[4] = "%Lg";
sfmt[2] = fmt;
return sprintf(str, sfmt, x);
if (((longdouble)(unsigned long long)x) == x)
{ // ((1.5 -> 1 -> 1.0) == 1.5) is false
// ((1.0 -> 1 -> 1.0) == 1.0) is true
// see http://en.cppreference.com/w/cpp/io/c/fprintf
char sfmt[5] = "%#Lg";
sfmt[3] = fmt;
return sprintf(str, sfmt, x);
}
else
{
char sfmt[4] = "%Lg";
sfmt[2] = fmt;
return sprintf(str, sfmt, x);
}
}
#if __MINGW32__
+12 -33
View File
@@ -987,6 +987,8 @@ void File::mark()
int File::read()
{
if (len)
return 0; // already read the file
#if POSIX
off_t size;
ssize_t numread;
@@ -1064,7 +1066,7 @@ err1:
name = this->name->toChars();
h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0);
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if (h == INVALID_HANDLE_VALUE)
goto err1;
@@ -1642,6 +1644,15 @@ void OutBuffer::prependbyte(unsigned b)
offset++;
}
void OutBuffer::writewchar(unsigned w)
{
#if _WIN32
writeword(w);
#else
write4(w);
#endif
}
void OutBuffer::writeword(unsigned w)
{
if (doindent && linehead
@@ -1740,36 +1751,6 @@ void OutBuffer::align(size_t size)
fill0(nbytes);
}
////////////////////////////////////////////////////////////////
// The compiler shipped with Visual Studio 2005 (and possible
// other versions) does not support C99 printf format specfiers
// such as %z and %j
#if 0 && _MSC_VER
using std::string;
using std::wstring;
template<typename S>
inline void
search_and_replace(S& str, const S& what, const S& replacement)
{
assert(!what.empty());
size_t pos = str.find(what);
while (pos != S::npos)
{
str.replace(pos, what.size(), replacement);
pos = str.find(what, pos + replacement.size());
}
}
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
S tmp = f; \
search_and_replace(fmt, S("%z"), S("%l")); \
search_and_replace(fmt, S("%j"), S("%l")); \
f = tmp.c_str();
#else
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
#endif
void OutBuffer::vprintf(const char *format, va_list args)
{
char buffer[128];
@@ -1777,8 +1758,6 @@ void OutBuffer::vprintf(const char *format, va_list args)
unsigned psize;
int count;
WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format);
p = buffer;
psize = sizeof(buffer);
for (;;)
+1
View File
@@ -258,6 +258,7 @@ struct OutBuffer : Object
void writebyte(unsigned b) { writeByte(b); }
void writeUTF8(unsigned b);
void prependbyte(unsigned b);
void writewchar(unsigned w);
void writeword(unsigned w);
void writeUTF16(unsigned w);
void write4(unsigned w);
+1 -1
View File
@@ -99,7 +99,7 @@ void StringValue::ctor(const char *p, size_t length)
memcpy(this->lstring, p, length * sizeof(char));
}
void StringTable::init(size_t size)
void StringTable::_init(size_t size)
{
table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size;
+2 -6
View File
@@ -24,11 +24,7 @@ struct StringEntry;
// method because the only thing which should be creating these is StringTable.
struct StringValue
{
union
{
void *ptrvalue;
char *string;
};
void *ptrvalue;
private:
size_t length;
@@ -59,7 +55,7 @@ private:
size_t tabledim;
public:
void init(size_t size = 37);
void _init(size_t size = 37);
~StringTable();
StringValue *lookup(const char *s, size_t len);
+210
View File
@@ -0,0 +1,210 @@
// Compiler implementation of the D programming language
// 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 <assert.h>
#include "mars.h"
#include "statement.h"
/**************************************
* A Statement tree walker that will visit each Statement s in the tree,
* in depth-first evaluation order, and call fp(s,param) on it.
* fp() signals whether the walking continues with its return value:
* Returns:
* 0 continue
* 1 done
* It's a bit slower than using virtual functions, but more encapsulated and less brittle.
* Creating an iterator for this would be much more complex.
*/
typedef bool (*sapply_fp_t)(Statement *, void *);
bool Statement::apply(sapply_fp_t fp, void *param)
{
return (*fp)(this, param);
}
/******************************
* Perform apply() on an t if not null
*/
#define scondApply(t, fp, param) (t ? t->apply(fp, param) : 0)
bool PeelStatement::apply(sapply_fp_t fp, void *param)
{
return s->apply(fp, param) ||
(*fp)(this, param);
}
bool CompoundStatement::apply(sapply_fp_t fp, void *param)
{
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = (*statements)[i];
bool r = scondApply(s, fp, param);
if (r)
return r;
}
return (*fp)(this, param);
}
bool UnrolledLoopStatement::apply(sapply_fp_t fp, void *param)
{
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = (*statements)[i];
bool r = scondApply(s, fp, param);
if (r)
return r;
}
return (*fp)(this, param);
}
bool ScopeStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
bool WhileStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
bool DoStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
bool ForStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(init, fp, param) ||
scondApply(body, fp, param) ||
(*fp)(this, param);
}
bool ForeachStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
#if DMDV2
bool ForeachRangeStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
#endif
bool IfStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(ifbody, fp, param) ||
scondApply(elsebody, fp, param) ||
(*fp)(this, param);
}
bool ConditionalStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(ifbody, fp, param) ||
scondApply(elsebody, fp, param) ||
(*fp)(this, param);
}
bool PragmaStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
bool SwitchStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
bool CaseStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
#if DMDV2
bool CaseRangeStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
#endif
bool DefaultStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
bool SynchronizedStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
bool WithStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
(*fp)(this, param);
}
bool TryCatchStatement::apply(sapply_fp_t fp, void *param)
{
bool r = scondApply(body, fp, param);
if (r)
return r;
for (size_t i = 0; i < catches->dim; i++)
{ Catch *c = (*catches)[i];
bool r = scondApply(c->handler, fp, param);
if (r)
return r;
}
return (*fp)(this, param);
}
bool TryFinallyStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(body, fp, param) ||
scondApply(finalbody, fp, param) ||
(*fp)(this, param);
}
bool OnScopeStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
bool DebugStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
bool LabelStatement::apply(sapply_fp_t fp, void *param)
{
return scondApply(statement, fp, param) ||
(*fp)(this, param);
}
+6 -4
View File
@@ -61,7 +61,8 @@ Scope::Scope()
this->sbreak = NULL;
this->scontinue = NULL;
this->fes = NULL;
this->structalign = global.structalign;
this->callsc = NULL;
this->structalign = STRUCTALIGN_DEFAULT;
this->func = NULL;
this->slabel = NULL;
this->linkage = LINKd;
@@ -74,7 +75,7 @@ Scope::Scope()
this->nofree = 0;
this->noctor = 0;
this->noaccesscheck = 0;
this->mustsemantic = 0;
this->needctfe = 0;
this->intypeof = 0;
this->speculative = 0;
this->parameterSpecialization = 0;
@@ -103,6 +104,7 @@ Scope::Scope(Scope *enclosing)
this->sbreak = enclosing->sbreak;
this->scontinue = enclosing->scontinue;
this->fes = enclosing->fes;
this->callsc = enclosing->callsc;
this->structalign = enclosing->structalign;
this->enclosing = enclosing;
#ifdef DEBUG
@@ -125,7 +127,7 @@ Scope::Scope(Scope *enclosing)
this->nofree = 0;
this->noctor = enclosing->noctor;
this->noaccesscheck = enclosing->noaccesscheck;
this->mustsemantic = enclosing->mustsemantic;
this->needctfe = enclosing->needctfe;
this->intypeof = enclosing->intypeof;
this->speculative = enclosing->speculative;
this->parameterSpecialization = enclosing->parameterSpecialization;
@@ -415,7 +417,7 @@ void *scope_search_fp(void *arg, const char *seed)
Scope *sc = (Scope *)arg;
Module::clearCache();
Dsymbol *s = sc->search(0, id, NULL);
Dsymbol *s = sc->search(Loc(), id, NULL);
return s;
}
+24 -22
View File
@@ -43,6 +43,25 @@ enum LINK;
enum PROT;
#endif
#define CSXthis_ctor 1 // called this()
#define CSXsuper_ctor 2 // called super()
#define CSXthis 4 // referenced this
#define CSXsuper 8 // referenced super
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
#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 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
struct Scope
{
Scope *enclosing; // enclosing Scope
@@ -61,6 +80,7 @@ struct Scope
Statement *sbreak; // enclosing statement that supports "break"
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
Scope *callsc; // used for __FUNCTION__, __PRETTY_FUNCTION__ and __MODULE__
unsigned offset; // next offset to use in aggregate
// This really shouldn't be a part of Scope, because it requires
// semantic() to be done in the lexical field order. It should be
@@ -73,17 +93,13 @@ struct Scope
bool speculative; // in __traits(compiles) or typeof(exp)
int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
int mustsemantic; // cannot defer semantic()
int needctfe; // inside a ctfe-only expression
#if IN_LLVM
int ignoreTemplates; // set if newly instantiated templates should be ignored when codegen'ing
#endif
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()
#define CSXsuper_ctor 2 // called super()
#define CSXthis 4 // referenced this
#define CSXsuper 8 // referenced super
#define CSXlabel 0x10 // seen a label
#define CSXreturn 0x20 // seen a return statement
#define CSXany_ctor 0x40 // either this() or super() was called
structalign_t structalign; // alignment for struct members
enum LINK linkage; // linkage for external functions
@@ -95,20 +111,7 @@ struct Scope
char *depmsg; // customized deprecation message
unsigned flags;
#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 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
#ifdef IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
Expressions *userAttributes; // user defined attributes
DocComment *lastdc; // documentation comment for last symbol at this scope
@@ -120,7 +123,6 @@ struct Scope
static Scope *createGlobal(Module *module);
Scope();
Scope(Module *module);
Scope(Scope *enclosing);
Scope *push();
+294 -557
View File
File diff suppressed because it is too large Load Diff
+45 -57
View File
@@ -56,7 +56,6 @@ struct InterState;
#if IN_LLVM
struct CaseStatement;
struct LabelStatement;
struct VolatileStatement;
struct SynchronizedStatement;
#endif
@@ -71,6 +70,8 @@ namespace llvm
}
#endif
typedef bool (*sapply_fp_t)(Statement *, void *);
// Back end
struct IRState;
struct Blockx;
@@ -125,13 +126,17 @@ struct Statement : Object
virtual Statement *getRelatedLabeled() { return this; }
virtual bool hasBreak();
virtual bool hasContinue();
virtual bool usesEH();
bool usesEH();
virtual bool usesEHimpl();
virtual int blockExit(bool mustNotThrow);
virtual int comeFrom();
virtual int isEmpty();
bool comeFrom();
virtual bool comeFromImpl();
bool hasCode();
virtual bool hasCodeImpl();
virtual Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
virtual Statements *flatten(Scope *sc);
virtual Expression *interpret(InterState *istate);
virtual bool apply(sapply_fp_t fp, void *param);
virtual Statement *last();
virtual int inlineCost(InlineCostState *ics);
@@ -164,6 +169,7 @@ struct PeelStatement : Statement
PeelStatement(Statement *s);
Statement *semantic(Scope *sc);
bool apply(sapply_fp_t fp, void *param);
};
struct ExpStatement : Statement
@@ -177,7 +183,7 @@ struct ExpStatement : Statement
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
int blockExit(bool mustNotThrow);
int isEmpty();
bool hasCodeImpl();
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
int inlineCost(InlineCostState *ics);
@@ -227,13 +233,12 @@ struct CompoundStatement : Statement
Statement *syntaxCopy();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
int isEmpty();
bool hasCodeImpl();
Statements *flatten(Scope *sc);
ReturnStatement *isReturnStatement();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
Statement *last();
int inlineCost(InlineCostState *ics);
@@ -270,10 +275,9 @@ struct UnrolledLoopStatement : Statement
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int inlineCost(InlineCostState *ics);
@@ -295,11 +299,10 @@ struct ScopeStatement : Statement
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
int isEmpty();
bool hasCodeImpl();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
@@ -319,10 +322,9 @@ struct WhileStatement : Statement
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
@@ -340,10 +342,9 @@ struct DoStatement : Statement
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
@@ -366,16 +367,15 @@ struct ForStatement : Statement
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
Statement *syntaxCopy();
Statement *semanticInit(Scope *sc);
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; }
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int inlineCost(InlineCostState *ics);
@@ -408,10 +408,9 @@ struct ForeachStatement : Statement
int inferApplyArgTypes(Scope *sc, Dsymbol *&sapply);
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
@@ -436,10 +435,9 @@ struct ForeachRangeStatement : Statement
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
@@ -461,8 +459,8 @@ struct IfStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
bool usesEH();
int blockExit(bool mustNotThrow);
IfStatement *isIfStatement() { return this; }
@@ -484,8 +482,8 @@ struct ConditionalStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
bool usesEH();
int blockExit(bool mustNotThrow);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
@@ -499,8 +497,8 @@ struct PragmaStatement : Statement
PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
bool usesEH();
int blockExit(bool mustNotThrow);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -542,9 +540,9 @@ struct SwitchStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
bool hasBreak();
bool usesEH();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
@@ -568,10 +566,10 @@ struct CaseStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int compare(Object *obj);
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
bool comeFromImpl();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
CaseStatement *isCaseStatement() { return this; }
@@ -596,6 +594,7 @@ struct CaseRangeStatement : Statement
CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
@@ -615,10 +614,10 @@ struct DefaultStatement : Statement
DefaultStatement(Loc loc, Statement *s);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
bool comeFromImpl();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
DefaultStatement *isDefaultStatement() { return this; }
@@ -740,8 +739,9 @@ struct SynchronizedStatement : Statement
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
bool usesEH();
bool usesEHimpl();
int blockExit(bool mustNotThrow);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
@@ -765,9 +765,9 @@ struct WithStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
bool usesEH();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
Statement *inlineScan(InlineScanState *iss);
@@ -783,9 +783,10 @@ struct TryCatchStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
bool hasBreak();
bool usesEH();
bool usesEHimpl();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
Statement *inlineScan(InlineScanState *iss);
@@ -821,9 +822,10 @@ struct TryFinallyStatement : Statement
Statement *semantic(Scope *sc);
bool hasBreak();
bool hasContinue();
bool usesEH();
bool usesEHimpl();
int blockExit(bool mustNotThrow);
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
Statement *inlineScan(InlineScanState *iss);
@@ -840,9 +842,10 @@ struct OnScopeStatement : Statement
int blockExit(bool mustNotThrow);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *semantic(Scope *sc);
bool usesEH();
bool usesEHimpl();
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toIR(IRState *irs);
};
@@ -865,22 +868,6 @@ struct ThrowStatement : Statement
void toIR(IRState *irs);
};
struct VolatileStatement : Statement
{
Statement *statement;
VolatileStatement(Loc loc, Statement *statement);
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
int blockExit(bool mustNotThrow);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
};
struct DebugStatement : Statement
{
Statement *statement;
@@ -889,6 +876,7 @@ struct DebugStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
@@ -931,10 +919,10 @@ struct LabelStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
Statements *flatten(Scope *sc);
bool usesEH();
int blockExit(bool mustNotThrow);
int comeFrom();
bool comeFromImpl();
Expression *interpret(InterState *istate);
bool apply(sapply_fp_t fp, void *param);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Statement *inlineScan(InlineScanState *iss);
@@ -968,7 +956,7 @@ struct AsmStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int blockExit(bool mustNotThrow);
int comeFrom();
bool comeFromImpl();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -995,7 +983,7 @@ struct ImportStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
int blockExit(bool mustNotThrow);
int isEmpty();
bool hasCodeImpl();
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+3 -3
View File
@@ -56,7 +56,7 @@ void StaticAssert::semantic2(Scope *sc)
sc = sc->push(sd);
sc->flags |= SCOPEstaticassert;
++sc->ignoreTemplates;
Expression *e = exp->semantic(sc);
Expression *e = exp->ctfeSemantic(sc);
e = resolveProperties(sc, e);
sc = sc->pop();
if (!e->type->checkBoolean())
@@ -77,7 +77,7 @@ void StaticAssert::semantic2(Scope *sc)
{ HdrGenState hgs;
OutBuffer buf;
msg = msg->semantic(sc);
msg = msg->ctfeSemantic(sc);
msg = resolveProperties(sc, msg);
msg = msg->ctfeInterpret();
hgs.console = 1;
@@ -129,7 +129,7 @@ void StaticAssert::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
exp->toCBuffer(buf, hgs);
if (msg)
{
buf->writeByte(',');
buf->writestring(", ");
msg->toCBuffer(buf, hgs);
}
buf->writestring(");");
+108 -70
View File
@@ -49,7 +49,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
stag = NULL;
sinit = NULL;
#endif
isnested = false;
enclosing = NULL;
vthis = NULL;
#if DMDV2
@@ -88,6 +88,7 @@ void AggregateDeclaration::semantic2(Scope *sc)
if (members)
{
sc = sc->push(this);
sc->parent = this;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
@@ -109,14 +110,25 @@ void AggregateDeclaration::semantic3(Scope *sc)
if (members)
{
sc = sc->push(this);
sc->parent = this;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
s->semantic3(sc);
}
sc->pop();
if (!getRTInfo)
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
Objects *tiargs = new Objects();
tiargs->push(type);
@@ -125,8 +137,8 @@ void AggregateDeclaration::semantic3(Scope *sc)
ti->semantic2(sc);
ti->semantic3(sc);
Dsymbol *s = ti->toAlias();
Expression *e = new DsymbolExp(0, s, 0);
e = e->semantic(ti->tempdecl->scope);
Expression *e = new DsymbolExp(Loc(), s, 0);
e = e->ctfeSemantic(ti->tempdecl->scope);
e = e->ctfeInterpret();
getRTInfo = e;
}
@@ -178,7 +190,7 @@ unsigned AggregateDeclaration::size(Loc loc)
v->semantic(NULL);
if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCctfe | STCtemplateparameter))
return 0;
if (v->storage_class & STCfield && v->sem >= SemanticDone)
if (v->isField() && v->sem >= SemanticDone)
return 0;
return 1;
}
@@ -209,7 +221,7 @@ Type *AggregateDeclaration::getType()
return type;
}
int AggregateDeclaration::isDeprecated()
bool AggregateDeclaration::isDeprecated()
{
return isdeprecated;
}
@@ -299,14 +311,68 @@ unsigned AggregateDeclaration::placeField(
/****************************************
* Returns !=0 if there's an extra member which is the 'this'
* Returns true if there's an extra member which is the 'this'
* pointer to the enclosing context (enclosing aggregate or function)
*/
int AggregateDeclaration::isNested()
bool AggregateDeclaration::isNested()
{
assert((isnested & ~1) == 0);
return isnested;
return enclosing != NULL;
}
void AggregateDeclaration::makeNested()
{
if (!enclosing && sizeok != SIZEOKdone && !isUnionDeclaration() && !isInterfaceDeclaration())
{
// If nested struct, add in hidden 'this' pointer to outer scope
if (!(storage_class & STCstatic))
{
Dsymbol *s = toParent2();
if (s)
{
AggregateDeclaration *ad = s->isAggregateDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
if (fd)
{
enclosing = fd;
}
else if (isClassDeclaration() && ad && ad->isClassDeclaration())
{
enclosing = ad;
}
else if (isStructDeclaration() && ad)
{
if (TemplateInstance *ti = ad->parent->isTemplateInstance())
{
enclosing = ti->enclosing;
}
}
if (enclosing)
{
//printf("makeNested %s, enclosing = %s\n", toChars(), enclosing->toChars());
Type *t;
if (ad)
t = ad->handle;
else if (fd)
{ AggregateDeclaration *ad2 = fd->isMember2();
if (ad2)
t = ad2->handle;
else
t = Type::tvoidptr;
}
else
assert(0);
if (t->ty == Tstruct)
t = Type::tvoidptr; // t should not be a ref type
assert(!vthis);
vthis = new ThisDeclaration(loc, t);
//vthis->storage_class |= STCref;
members->push(vthis);
}
}
}
}
}
/****************************************
@@ -383,12 +449,16 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
type = new TypeStruct(this);
#if MODULEINFO_IS_STRUCT
#ifdef DMDV2
if (id == Id::ModuleInfo && !Module::moduleinfo)
Module::moduleinfo = this;
#else
if (id == Id::ModuleInfo)
{
if (Module::moduleinfo)
Module::moduleinfo->error("only object.d can define this reserved class name");
{ if (Module::moduleinfo)
Module::moduleinfo->error("only object.d can define this reserved struct name");
Module::moduleinfo = this;
}
#endif
#endif
}
@@ -413,7 +483,7 @@ void StructDeclaration::semantic(Scope *sc)
//static int count; if (++count == 20) halt();
assert(type);
if (!members) // if forward reference
if (!members) // if opaque declaration
{
return;
}
@@ -435,7 +505,7 @@ void StructDeclaration::semantic(Scope *sc)
scope = NULL;
}
int errors = global.gaggedErrors;
int errors = global.errors;
unsigned dprogress_save = Module::dprogress;
@@ -594,7 +664,7 @@ void StructDeclaration::semantic(Scope *sc)
arguments->push(arg);
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), sc);
}
TypeFunction *tfeq;
@@ -604,7 +674,7 @@ void StructDeclaration::semantic(Scope *sc)
arguments->push(arg);
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeq = (TypeFunction *)tfeq->semantic(0, sc);
tfeq = (TypeFunction *)tfeq->semantic(Loc(), sc);
}
Identifier *id = Id::eq;
@@ -643,22 +713,20 @@ void StructDeclaration::semantic(Scope *sc)
postblit = buildPostBlit(sc2);
cpctor = buildCpCtor(sc2);
hasIdentityAssign = (buildOpAssign(sc2) != NULL);
hasIdentityEquals = (buildOpEquals(sc2) != NULL);
xeq = buildXopEquals(sc2);
buildOpAssign(sc2);
buildOpEquals(sc2);
#endif
inv = buildInv(sc2);
sc2->pop();
/* Look for special member functions.
*/
#if DMDV2
ctor = search(0, Id::ctor, 0);
ctor = search(Loc(), Id::ctor, 0);
#endif
inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0);
aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
aggNew = (NewDeclaration *)search(Loc(), Id::classNew, 0);
aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete, 0);
TypeTuple *tup = type->toArgTypes();
size_t dim = tup->arguments->dim;
@@ -675,8 +743,8 @@ void StructDeclaration::semantic(Scope *sc)
semantic3(sc);
}
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
if (global.errors != errors)
{ // The type is no good.
type = Type::terror;
}
@@ -685,6 +753,15 @@ void StructDeclaration::semantic(Scope *sc)
deferred->semantic2(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);
}
#endif
assert(type->ty != Tstruct || ((TypeStruct *)type)->sym == this);
}
Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
@@ -694,7 +771,7 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
if (scope && !symtab)
semantic(scope);
if (!members || !symtab)
if (!members || !symtab) // opaque or semantic() is not yet called
{
error("is forward referenced when looking for '%s'", ident->toChars());
return NULL;
@@ -737,45 +814,6 @@ void StructDeclaration::finalizeSize(Scope *sc)
sizeok = SIZEOKdone;
}
void StructDeclaration::makeNested()
{
if (!isnested && sizeok != SIZEOKdone && !isUnionDeclaration())
{
// If nested struct, add in hidden 'this' pointer to outer scope
if (!(storage_class & STCstatic))
{ Dsymbol *s = toParent2();
if (s)
{
AggregateDeclaration *ad = s->isAggregateDeclaration();
FuncDeclaration *fd = s->isFuncDeclaration();
TemplateInstance *ti;
if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd)
{ isnested = true;
Type *t;
if (ad)
t = ad->handle;
else if (fd)
{ AggregateDeclaration *ad = fd->isMember2();
if (ad)
t = ad->handle;
else
t = Type::tvoidptr;
}
else
assert(0);
if (t->ty == Tstruct)
t = Type::tvoidptr; // t should not be a ref type
assert(!vthis);
vthis = new ThisDeclaration(loc, t);
//vthis->storage_class |= STCref;
members->push(vthis);
}
}
}
}
}
/***************************************
* Return true if struct is POD (Plain Old Data).
* This is defined as:
@@ -790,7 +828,7 @@ void StructDeclaration::makeNested()
*/
bool StructDeclaration::isPOD()
{
if (isnested || cpctor || postblit || ctor || dtor)
if (enclosing || cpctor || postblit || ctor || dtor)
return false;
/* Recursively check any fields have a constructor.
@@ -800,7 +838,7 @@ bool StructDeclaration::isPOD()
{
Dsymbol *s = fields[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
assert(v && v->isField());
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
+125
View File
@@ -0,0 +1,125 @@
// Copyright (c) 2013 by Digital Mars
// All Rights Reserved
// written by Iain Buclaw
// 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 <assert.h>
#include "target.h"
#include "mars.h"
#include "mtype.h"
#if IN_LLVM
unsigned GetTypeAlignment(Type* t);
unsigned GetPointerSize();
unsigned GetTypeStoreSize(Type* t);
unsigned GetTypeAllocSize(Type* t);
#endif
int Target::ptrsize;
int Target::realsize;
int Target::realpad;
int Target::realalignsize;
void Target::init()
{
#if IN_LLVM
ptrsize = GetPointerSize();
realsize = GetTypeAllocSize(Type::basic[Tfloat80]);
realpad = realsize - GetTypeStoreSize(Type::basic[Tfloat80]);
realalignsize = GetTypeAlignment(Type::basic[Tfloat80]);
#else
// These have default values for 32 bit code, they get
// adjusted for 64 bit code.
ptrsize = 4;
if (global.params.isLinux || global.params.isFreeBSD
|| global.params.isOpenBSD || global.params.isSolaris)
{
realsize = 12;
realpad = 2;
realalignsize = 4;
}
else if (global.params.isOSX)
{
realsize = 16;
realpad = 6;
realalignsize = 16;
}
else if (global.params.isWindows)
{
realsize = 10;
realpad = 0;
realalignsize = 2;
}
else
assert(0);
if (global.params.is64bit)
{
ptrsize = 8;
if (global.params.isLinux || global.params.isFreeBSD || global.params.isSolaris)
{
realsize = 16;
realpad = 6;
realalignsize = 16;
}
}
#endif
}
/******************************
* Return memory alignment size of type.
*/
unsigned Target::alignsize (Type* type)
{
assert (type->isTypeBasic());
#if IN_LLVM
if (type->ty == Tvoid) return 1;
return GetTypeAlignment(type);
#else
switch (type->ty)
{
case Tfloat80:
case Timaginary80:
case Tcomplex80:
return Target::realalignsize;
case Tcomplex32:
if (global.params.isLinux || global.params.isOSX || global.params.isFreeBSD
|| global.params.isOpenBSD || global.params.isSolaris)
return 4;
break;
case Tint64:
case Tuns64:
case Tfloat64:
case Timaginary64:
case Tcomplex64:
if (global.params.isLinux || global.params.isOSX || global.params.isFreeBSD
|| global.params.isOpenBSD || global.params.isSolaris)
return global.params.is64bit ? 8 : 4;
break;
default:
break;
}
return type->size(Loc());
#endif
}
/******************************
* Return field alignment size of type.
*/
unsigned Target::fieldalign (Type* type)
{
// LDC_FIXME: Verify this.
return type->alignsize();
}
+31
View File
@@ -0,0 +1,31 @@
// Copyright (c) 2013 by Digital Mars
// All Rights Reserved
// written by Iain Buclaw
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#ifndef TARGET_H
#define TARGET_H
// This file contains a data structure that describes a back-end target.
// 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;
struct Target
{
static int ptrsize;
static int realsize; // size a real consumes in memory
static int realpad; // 'padding' added to the CPU real size to bring it up to realsize
static int realalignsize; // alignment for reals
static void init();
static unsigned alignsize(Type* type);
static unsigned fieldalign(Type* type);
};
#endif
+660 -619
View File
File diff suppressed because it is too large Load Diff
+13 -11
View File
@@ -34,6 +34,7 @@ struct TemplateValueParameter;
struct TemplateAliasParameter;
struct TemplateTupleParameter;
struct Type;
struct TypeQualified;
struct TypeTypeof;
struct Scope;
struct Expression;
@@ -90,15 +91,17 @@ struct TemplateDeclaration : ScopeDsymbol
void emitComment(Scope *sc);
void toJson(JsonOut *json);
virtual void jsonProperties(JsonOut *json);
enum PROT prot();
// void toDocBuffer(OutBuffer *buf);
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag);
MATCH leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs);
MATCH deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
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);
FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Expressions *fargs);
FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Type *tthis, Expressions *fargs);
TemplateDeclaration *isTemplateDeclaration() { return this; }
@@ -304,7 +307,7 @@ struct TemplateInstance : ScopeDsymbol
int semantictiargsdone; // has semanticTiargs() been done?
int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
Dsymbol *isnested; // if referencing local symbols, this is the context
Dsymbol *enclosing; // if referencing local symbols, this is the context
int speculative; // 1 if only instantiated with errors gagged
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
@@ -328,7 +331,7 @@ struct TemplateInstance : ScopeDsymbol
int oneMember(Dsymbol **ps, Identifier *ident);
int needsTypeInference(Scope *sc);
char *toChars();
char *mangle(bool isv = false);
const char *mangle(bool isv = false);
void printInstantiationTrace();
#if IN_DMD
@@ -337,9 +340,9 @@ struct TemplateInstance : ScopeDsymbol
// Internal
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
void semanticTiargs(Scope *sc);
TemplateDeclaration *findTemplateDeclaration(Scope *sc);
TemplateDeclaration *findBestMatch(Scope *sc, Expressions *fargs);
bool semanticTiargs(Scope *sc);
bool findTemplateDeclaration(Scope *sc);
bool findBestMatch(Scope *sc, Expressions *fargs);
void declareParameters(Scope *sc);
int hasNestedArgs(Objects *tiargs);
Identifier *genIdent(Objects *args);
@@ -361,10 +364,9 @@ struct TemplateInstance : ScopeDsymbol
struct TemplateMixin : TemplateInstance
{
Identifiers *idents;
Type *tqual;
TypeQualified *tqual;
TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Identifiers *idents, Objects *tiargs);
TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void semantic2(Scope *sc);
+61 -22
View File
@@ -61,10 +61,12 @@ static int fptraits(void *param, FuncDeclaration *f)
return 0;
Expression *e;
FuncAliasDeclaration* alias = new FuncAliasDeclaration(f, 0);
alias->protection = f->protection;
if (p->e1)
e = new DotVarExp(0, p->e1, new FuncAliasDeclaration(f, 0));
e = new DotVarExp(Loc(), p->e1, alias);
else
e = new DsymbolExp(0, new FuncAliasDeclaration(f, 0));
e = new DsymbolExp(Loc(), alias);
p->exps->push(e);
return 0;
}
@@ -168,6 +170,34 @@ Expression *TraitsExp::semantic(Scope *sc)
}
goto Ltrue;
}
else if (ident == Id::isNested)
{
if (dim != 1)
goto Ldimerror;
Object *o = (*args)[0];
Dsymbol *s = getDsymbol(o);
AggregateDeclaration *a;
FuncDeclaration *f;
if (!s) { }
else if ((a = s->isAggregateDeclaration()) != NULL)
{
if (a->isNested())
goto Ltrue;
else
goto Lfalse;
}
else if ((f = s->isFuncDeclaration()) != NULL)
{
if (f->isNested())
goto Ltrue;
else
goto Lfalse;
}
error("aggregate or function expected instead of '%s'", o->toChars());
goto Lfalse;
}
else if (ident == Id::isAbstractFunction)
{
FuncDeclaration *f;
@@ -254,6 +284,7 @@ Expression *TraitsExp::semantic(Scope *sc)
const char *protName = Pprotectionnames[protection];
assert(protName);
StringExp *se = new StringExp(loc, (char *) protName);
return se->semantic(sc);
}
@@ -305,17 +336,17 @@ Expression *TraitsExp::semantic(Scope *sc)
}
Identifier *id = Lexer::idPool((char *)se->string);
Type *t = isType(o);
e = isExpression(o);
Dsymbol *s = isDsymbol(o);
if (t)
e = typeDotIdExp(loc, t, id);
else if (e)
e = new DotIdExp(loc, e, id);
else if (s)
{ e = new DsymbolExp(loc, s);
/* Prefer dsymbol, because it might need some runtime contexts.
*/
Dsymbol *sym = getDsymbol(o);
if (sym)
{ e = new DsymbolExp(loc, sym);
e = new DotIdExp(loc, e, id);
}
else if (Type *t = isType(o))
e = typeDotIdExp(loc, t, id);
else if (Expression *ex = isExpression(o))
e = new DotIdExp(loc, ex, id);
else
{ error("invalid first argument");
goto Lfalse;
@@ -323,21 +354,16 @@ Expression *TraitsExp::semantic(Scope *sc)
if (ident == Id::hasMember)
{
if (t)
if (sym)
{
Dsymbol *sym = t->toDsymbol(sc);
if (sym)
{
Dsymbol *sm = sym->search(loc, id, 0);
if (sm)
goto Ltrue;
}
Dsymbol *sm = sym->search(loc, id, 0);
if (sm)
goto Ltrue;
}
/* Take any errors as meaning it wasn't found
*/
Scope *sc2 = sc->push();
//sc2->inHasMember++;
e = e->trySemantic(sc2);
sc2->pop();
if (!e)
@@ -384,7 +410,7 @@ Expression *TraitsExp::semantic(Scope *sc)
p.exps = exps;
p.e1 = e;
p.ident = ident;
overloadApply(f, fptraits, &p);
overloadApply(f, &fptraits, &p);
TupleExp *tup = new TupleExp(loc, exps);
return tup->semantic(sc);
@@ -435,7 +461,12 @@ Expression *TraitsExp::semantic(Scope *sc)
error("argument has no members");
goto Lfalse;
}
if ((sd = s->isScopeDsymbol()) == NULL)
Import *import;
if ((import = s->isImport()) != NULL)
{ // Bugzilla 9692
sd = import->mod;
}
else if ((sd = s->isScopeDsymbol()) == NULL)
{
error("%s %s has no members", s->kind(), s->toChars());
goto Lfalse;
@@ -468,6 +499,14 @@ Expression *TraitsExp::semantic(Scope *sc)
idents->push(sm->ident);
}
else
{
EnumDeclaration *ed = sm->isEnumDeclaration();
if (ed)
{
ScopeDsymbol::foreach(NULL, ed->members, &PushIdentsDg::dg, (Identifiers *)ctx);
}
}
return 0;
}
};
-12
View File
@@ -19,9 +19,6 @@
#include "utf.h"
namespace
{
/* The following encodings are valid, except for the 5 and 6 byte
* combinations:
* 0xxxxxxx
@@ -51,11 +48,6 @@ const unsigned UTF8_STRIDE[256] =
4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
};
} // namespace
namespace Unicode
{
// UTF-8 decoding errors
char const UTF8_DECODE_OUTSIDE_CODE_SPACE[] = "Outside Unicode code space";
char const UTF8_DECODE_TRUNCATED_SEQUENCE[] = "Truncated UTF-8 sequence";
@@ -69,10 +61,6 @@ char const UTF16_DECODE_INVALID_SURROGATE[] = "Invalid low surrogate";
char const UTF16_DECODE_UNPAIRED_SURROGATE[]= "Unpaired surrogate";
char const UTF16_DECODE_INVALID_CODE_POINT[]= "Invalid code point decoded";
} // namespace Unicode
using namespace Unicode;
/// The Unicode code space is the range of code points [0x000000,0x10FFFF]
/// except the UTF-16 surrogate pairs in the range [0xD800,0xDFFF]
/// and non-characters (which end in 0xFFFE or 0xFFFF).
-5
View File
@@ -20,9 +20,6 @@ typedef unsigned short utf16_t;
typedef unsigned int utf32_t;
typedef utf32_t dchar_t;
namespace Unicode
{
static utf16_t const ALPHA_TABLE[][2] =
{
{ 0x00AA, 0x00AA }, { 0x00B5, 0x00B5 }, { 0x00B7, 0x00B7 }, { 0x00BA, 0x00BA },
@@ -102,8 +99,6 @@ extern char const UTF16_DECODE_INVALID_SURROGATE[];
extern char const UTF16_DECODE_UNPAIRED_SURROGATE[];
extern char const UTF16_DECODE_INVALID_CODE_POINT[];
} // namespace Unicode
/// \return true if \a c is a valid, non-private UTF-32 code point
bool utf_isValidDchar(dchar_t c);
+6 -1
View File
@@ -14,6 +14,7 @@
#include "mtype.h"
#include "rmem.h"
#include "root.h"
#include "dmd2/target.h"
#include "driver/cl_options.h"
#include "driver/configfile.h"
#include "driver/linker.h"
@@ -163,6 +164,8 @@ int main(int argc, char** argv)
Module *m;
int status = EXIT_SUCCESS;
global.init();
// Set some default values
#if _WIN32
char buf[MAX_PATH];
@@ -648,6 +651,7 @@ int main(int argc, char** argv)
Type::init(&ir);
Id::initialize();
Module::init();
Target::init();
initPrecedence();
backend_init();
@@ -808,7 +812,7 @@ int main(int argc, char** argv)
if (!Module::rootModule)
Module::rootModule = m;
m->importedFrom = m;
m->read(0);
m->read(Loc());
m->parse(global.params.doDocComments);
m->buildTargetFiles(singleObj);
m->deleteObjFile();
@@ -924,6 +928,7 @@ int main(int argc, char** argv)
if (global.errors)
fatal();
}
global.inExtraInliningSemantic = false;
}
if (global.errors || global.warnings)
fatal();
+4 -4
View File
@@ -1546,7 +1546,7 @@ namespace AsmParserx8664
for ( int i = 0; i < N_PtrNames; i++ )
ptrTypeIdentTable[i] = Lexer::idPool ( ptrTypeNameTable[i] );
Handled = new Expression ( 0, TOKvoid, sizeof ( Expression ) );
Handled = new Expression ( Loc(), TOKvoid, sizeof ( Expression ) );
ident_seg = Lexer::idPool ( "seg" );
@@ -2474,7 +2474,7 @@ namespace AsmParserx8664
#endif
{
e = new AddrExp ( 0, e );
e = new AddrExp ( Loc(), e );
e->type = decl->type->pointerTo();
operand->constDisplacement = 0;
@@ -2539,7 +2539,7 @@ namespace AsmParserx8664
if ( !sc->func->naked ) // no addrexp in naked asm please :)
{
Type* tt = e->type->pointerTo();
e = new AddrExp ( 0, e );
e = new AddrExp ( Loc(), e );
e->type = tt;
}
@@ -2696,7 +2696,7 @@ namespace AsmParserx8664
// DMD doesn't check Tcomplex*, and counts Tcomplex32 as Tfloat64
TY ty = v->type->toBasetype()->ty;
operand->dataSizeHint = ty == Tfloat80 || ty == Timaginary80 ?
Extended_Ptr : ( PtrType ) v->type->size ( 0 );
Extended_Ptr : ( PtrType ) v->type->size ( Loc() );
}
if ( ! operand->symbolDisplacement.dim )
+1 -6
View File
@@ -132,11 +132,6 @@ void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
}
int AsmStatement::comeFrom()
{
return FALSE;
}
struct AsmParserCommon
{
virtual ~AsmParserCommon() {}
@@ -577,7 +572,7 @@ void AsmBlockStatement::toIR(IRState* p)
{
FuncDeclaration* fd = gIR->func()->decl;
char* fdmangle = fd->mangle();
const char* fdmangle = fd->mangle();
// we use a simple static counter to make sure the new end labels are unique
static size_t uniqueLabelsId = 0;
+2 -1
View File
@@ -12,6 +12,7 @@
#include "declaration.h"
#include "init.h"
#include "mtype.h"
#include "target.h"
#include "gen/arrays.h"
#include "gen/classes.h"
#include "gen/dvalue.h"
@@ -198,7 +199,7 @@ void DtoInitClass(TypeClass* tc, LLValue* dst)
{
tc->sym->codegen(Type::sir);
uint64_t n = tc->sym->structsize - PTRSIZE * 2;
uint64_t n = tc->sym->structsize - Target::ptrsize * 2;
// set vtable field seperately, this might give better optimization
LLValue* tmp = DtoGEPi(dst,0,0,"vtbl");
+1 -9
View File
@@ -252,7 +252,7 @@ void DtoGoto(Loc loc, Identifier* target, TryFinallyStatement* sourceFinally)
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// TRY-FINALLY, VOLATILE AND SYNCHRONIZED HELPER
// TRY-FINALLY AND SYNCHRONIZED HELPER
////////////////////////////////////////////////////////////////////////////////////////*/
void EnclosingSynchro::emitCode(IRState * p)
@@ -265,14 +265,6 @@ void EnclosingSynchro::emitCode(IRState * p)
////////////////////////////////////////////////////////////////////////////////////////
void EnclosingVolatile::emitCode(IRState * p)
{
// store-load barrier
DtoMemoryBarrier(false, false, true, false);
}
////////////////////////////////////////////////////////////////////////////////////////
void EnclosingTryFinally::emitCode(IRState * p)
{
if (tf->finalbody)
-6
View File
@@ -35,12 +35,6 @@ struct EnclosingTryFinally : EnclosingHandler
EnclosingTryFinally(TryFinallyStatement* _tf, llvm::BasicBlock* _pad)
: tf(_tf), landingPad(_pad) {}
};
struct EnclosingVolatile : EnclosingHandler
{
VolatileStatement* v;
void emitCode(IRState* p);
EnclosingVolatile(VolatileStatement* _tf) : v(_tf) {}
};
struct EnclosingSynchro : EnclosingHandler
{
SynchronizedStatement* s;
+2 -1
View File
@@ -19,6 +19,7 @@
#include "mtype.h"
#include "scope.h"
#include "statement.h"
#include "target.h"
#include "template.h"
#include "gen/abi.h"
#include "gen/arrays.h"
@@ -357,7 +358,7 @@ void Module::genmoduleinfo()
// check for patch
else
{
unsigned sizeof_ModuleInfo = 16 * PTRSIZE;
unsigned sizeof_ModuleInfo = 16 * Target::ptrsize;
if (sizeof_ModuleInfo != moduleinfo->structsize)
{
error("object.d ModuleInfo class is incorrect");
+2 -1
View File
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
#include "target.h"
#include "gen/nested.h"
#include "gen/dvalue.h"
#include "gen/functions.h"
@@ -444,7 +445,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
if (depth > 1) {
src = DtoBitCast(src, getVoidPtrType());
LLValue* dst = DtoBitCast(frame, getVoidPtrType());
DtoMemCpy(dst, src, DtoConstSize_t((depth-1) * PTRSIZE),
DtoMemCpy(dst, src, DtoConstSize_t((depth-1) * Target::ptrsize),
getABITypeAlign(getVoidPtrType()));
}
// Copy nestArg into framelist; the outer frame is not in the list of pointers
-43
View File
@@ -1557,48 +1557,6 @@ void SynchronizedStatement::toIR(IRState* p)
//////////////////////////////////////////////////////////////////////////////
void VolatileStatement::toIR(IRState* p)
{
Logger::println("VolatileStatement::toIR(): %s", loc.toChars());
LOG_SCOPE;
// emit dwarf stop point
DtoDwarfStopPoint(loc.linnum);
// mark in-volatile
// FIXME
// has statement
if (statement != NULL)
{
// load-store
DtoMemoryBarrier(false, true, false, false);
// do statement
p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL));
statement->toIR(p);
p->func()->gen->targetScopes.pop_back();
// no point in a unreachable barrier, terminating statements must insert this themselves.
if (statement->blockExit(false) & BEfallthru)
{
// store-load
DtoMemoryBarrier(false, false, true, false);
}
}
// barrier only
else
{
// load-store & store-load
DtoMemoryBarrier(false, true, true, false);
}
// restore volatile state
// FIXME
}
//////////////////////////////////////////////////////////////////////////////
void SwitchErrorStatement::toIR(IRState* p)
{
Logger::println("SwitchErrorStatement::toIR(): %s", loc.toChars());
@@ -1653,7 +1611,6 @@ STUBST(Statement);
//STUBST(AsmStatement);
//STUBST(TryCatchStatement);
//STUBST(TryFinallyStatement);
//STUBST(VolatileStatement);
//STUBST(LabelStatement);
//STUBST(ThrowStatement);
//STUBST(GotoCaseStatement);
+6 -5
View File
@@ -10,6 +10,7 @@
#include "declaration.h"
#include "id.h"
#include "mtype.h"
#include "target.h"
#include "gen/abi.h"
#include "gen/dvalue.h"
#include "gen/functions.h"
@@ -211,24 +212,24 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args,
assert(argexp->type->ty != Ttuple);
vtypes.push_back(DtoType(argexp->type));
size_t sz = getTypePaddedSize(vtypes.back());
size_t asz = (sz + PTRSIZE - 1) & ~(PTRSIZE -1);
size_t asz = (sz + Target::ptrsize - 1) & ~(Target::ptrsize -1);
if (sz != asz)
{
if (sz < PTRSIZE)
if (sz < Target::ptrsize)
{
vtypes.back() = DtoSize_t();
}
else
{
// ok then... so we build some type that is big enough
// and aligned to PTRSIZE
// and aligned to Target::ptrsize
std::vector<LLType*> gah;
gah.reserve(asz/PTRSIZE);
gah.reserve(asz/Target::ptrsize);
size_t gah_sz = 0;
while (gah_sz < asz)
{
gah.push_back(DtoSize_t());
gah_sz += PTRSIZE;
gah_sz += Target::ptrsize;
}
vtypes.back() = LLStructType::get(gIR->context(), gah, true);
}
+1 -1
View File
@@ -187,7 +187,7 @@ static llvm::DIType dwarfVectorType(Type* type)
assert(t->ty == Tvector && "only vectors allowed for debug info in dwarfVectorType");
TypeVector *tv = static_cast<TypeVector *>(t);
Type *te = tv->elementType();
int64_t Dim = tv->size(Loc(0)) / te->size(Loc(0));
int64_t Dim = tv->size(Loc()) / te->size(Loc());
llvm::Value *subscripts[] =
{
gIR->dibuilder.getOrCreateSubrange(0, Dim)
+2 -2
View File
@@ -120,7 +120,7 @@ LLConstant* VarExp::toConstElem(IRState* p)
Logger::print("VarExp::toConstElem: %s @ %s\n", toChars(), type->toChars());
LOG_SCOPE;
if (StaticStructInitDeclaration* sdecl = var->isStaticStructInitDeclaration())
if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
{
// this seems to be the static initialiser for structs
Type* sdecltype = sdecl->type->toBasetype();
@@ -2086,7 +2086,7 @@ DValue* AssertExp::toElem(IRState* p)
p->scope() = IRScope(endbb,oldend);
InvariantDeclaration* invdecl;
FuncDeclaration* invdecl;
// class invariants
if(
global.params.useInvariants &&
+9 -9
View File
@@ -97,7 +97,7 @@ Expression *Type::getInternalTypeInfo(Scope *sc)
{ tid = new TypeInfoDeclaration(t, 1);
internalTI[t->ty] = tid;
}
e = new VarExp(0, tid);
e = new VarExp(Loc(), tid);
e = e->addressOf(sc);
e->type = tid->type; // do this so we don't get redundant dereference
return e;
@@ -118,7 +118,7 @@ Expression *Type::getTypeInfo(Scope *sc)
//printf("Type::getTypeInfo() %p, %s\n", this, toChars());
if (!Type::typeinfo)
{
error(0, "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch");
error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch");
fatal();
}
@@ -159,7 +159,7 @@ Expression *Type::getTypeInfo(Scope *sc)
}
}
}
e = new VarExp(0, t->vtinfo);
e = new VarExp(Loc(), t->vtinfo);
e = e->addressOf(sc);
e->type = t->vtinfo->type; // do this so we don't get redundant dereference
return e;
@@ -409,7 +409,7 @@ void TypeInfoTypedefDeclaration::llvmDefine()
// void[] init
// emit null array if we should use the basetype, or if the basetype
// uses default initialization.
if (tinfo->isZeroInit(0) || !sd->init)
if (tinfo->isZeroInit(Loc()) || !sd->init)
{
b.push_null_void_array();
}
@@ -446,7 +446,7 @@ void TypeInfoEnumDeclaration::llvmDefine()
// void[] init
// emit void[] with the default initialier, the array is null if the default
// initializer is zero
if (!sd->defaultval || tinfo->isZeroInit(0))
if (!sd->defaultval || tinfo->isZeroInit(Loc()))
{
b.push_null_void_array();
}
@@ -618,7 +618,7 @@ void TypeInfoStructDeclaration::llvmDefine()
// The protocol is to write a null pointer for zero-initialized arrays. The
// length field is always needed for tsize().
llvm::Constant *initPtr;
if (tc->isZeroInit(0))
if (tc->isZeroInit(Loc()))
initPtr = getNullValue(getVoidPtrType());
else
initPtr = irstruct->getInitSymbol();
@@ -633,11 +633,11 @@ void TypeInfoStructDeclaration::llvmDefine()
Scope sc;
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
tftohash ->mod = MODconst;
tftohash = static_cast<TypeFunction *>(tftohash->semantic(0, &sc));
tftohash = static_cast<TypeFunction *>(tftohash->semantic(Loc(), &sc));
Type *retType = Type::tchar->invariantOf()->arrayOf();
tftostring = new TypeFunction(NULL, retType, 0, LINKd);
tftostring = static_cast<TypeFunction *>(tftostring->semantic(0, &sc));
tftostring = static_cast<TypeFunction *>(tftostring->semantic(Loc(), &sc));
}
// this one takes a parameter, so we need to build a new one each time
@@ -652,7 +652,7 @@ void TypeInfoStructDeclaration::llvmDefine()
arguments->push(arg);
tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfcmpptr->mod = MODconst;
tfcmpptr = static_cast<TypeFunction *>(tfcmpptr->semantic(0, &sc));
tfcmpptr = static_cast<TypeFunction *>(tfcmpptr->semantic(Loc(), &sc));
}
// well use this module for all overload lookups
+4 -4
View File
@@ -23,22 +23,22 @@
#include "ir/irfunction.h"
unsigned GetTypeAlignment(Ir* ir, Type* t)
unsigned GetTypeAlignment(Type* t)
{
return gDataLayout->getABITypeAlignment(DtoType(t));
}
unsigned GetPointerSize(Ir* ir)
unsigned GetPointerSize()
{
return gDataLayout->getPointerSize(ADDRESS_SPACE);
}
unsigned GetTypeStoreSize(Ir* ir, Type* t)
unsigned GetTypeStoreSize(Type* t)
{
return gDataLayout->getTypeStoreSize(DtoType(t));
}
unsigned GetTypeAllocSize(Ir* ir, Type* t)
unsigned GetTypeAllocSize(Type* t)
{
return gDataLayout->getTypeAllocSize(DtoType(t));
}
+4 -3
View File
@@ -12,6 +12,7 @@
#include "declaration.h"
#include "init.h"
#include "mtype.h"
#include "target.h"
#include "gen/irstate.h"
#include "gen/llvmhelpers.h"
#include "gen/logger.h"
@@ -256,7 +257,7 @@ llvm::Constant* IrAggr::createInitializerConstant(
constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo())));
// we start right after the vtbl and monitor
offset = PTRSIZE * 2;
offset = Target::ptrsize * 2;
}
addFieldInitializers(constants, explicitInitializers, aggrdecl, offset);
@@ -409,14 +410,14 @@ void IrAggr::addFieldInitializers(
size_t inter_idx = interfacesWithVtbls.size();
offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);
offset = (offset + Target::ptrsize - 1) & ~(Target::ptrsize - 1);
ArrayIter<BaseClass> it2(*cd->vtblInterfaces);
for (; !it2.done(); it2.next())
{
BaseClass* b = it2.get();
constants.push_back(getInterfaceVtbl(b, newinsts, inter_idx));
offset += PTRSIZE;
offset += Target::ptrsize;
// add to the interface list
interfacesWithVtbls.push_back(b);
+1
View File
@@ -19,6 +19,7 @@
#include "aggregate.h"
#include "declaration.h"
#include "mtype.h"
#include "target.h"
#include "gen/irstate.h"
#include "gen/logger.h"
+4 -3
View File
@@ -17,6 +17,7 @@
#include "declaration.h"
#include "dsymbol.h"
#include "mtype.h"
#include "target.h"
#include "template.h"
#include "gen/irstate.h"
@@ -190,7 +191,7 @@ void IrTypeClass::addBaseClassData(
Type* first = interfaces_idx->type->nextOf()->pointerTo();
// align offset
offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);
offset = (offset + Target::ptrsize - 1) & ~(Target::ptrsize - 1);
for (; !it2.done(); it2.next())
{
@@ -203,7 +204,7 @@ void IrTypeClass::addBaseClassData(
llvm::Type* ivtbl_type = llvm::StructType::get(gIR->context(), buildVtblType(first, &arr));
defaultTypes.push_back(llvm::PointerType::get(ivtbl_type, 0));
offset += PTRSIZE;
offset += Target::ptrsize;
// add to the interface map
addInterfaceToMap(b->base, field_index);
@@ -256,7 +257,7 @@ IrTypeClass* IrTypeClass::get(ClassDeclaration* cd)
defaultTypes.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(gIR->context()), 0));
// we start right after the vtbl and monitor
size_t offset = PTRSIZE * 2;
size_t offset = Target::ptrsize * 2;
size_t field_index = 2;
// add data members recursively