mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-16 02:17:07 +02:00
Merge the 2.063 frontend.
This commit is contained in:
+28
-27
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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; \
|
||||
}
|
||||
|
||||
|
||||
@@ -76,4 +76,5 @@ typedef ArrayBase<struct block> Blocks;
|
||||
|
||||
typedef ArrayBase<struct Symbol> Symbols;
|
||||
|
||||
typedef ArrayBase<struct dt_t> Dts;
|
||||
#endif
|
||||
|
||||
+105
-120
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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, ¶meters, &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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 = /</</\n\
|
||||
/&/&/\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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+106
-27
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+126
-79
@@ -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
File diff suppressed because it is too large
Load Diff
+3
-2
@@ -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()
|
||||
|
||||
@@ -36,7 +36,6 @@ struct Identifier : Object
|
||||
int compare(Object *o);
|
||||
void print();
|
||||
char *toChars();
|
||||
char *toHChars();
|
||||
const char *toHChars2();
|
||||
int dyncast();
|
||||
|
||||
|
||||
+5
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+89
-77
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+5
-4
@@ -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
@@ -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
@@ -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
@@ -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 (;;)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+45
-57
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+13
-11
@@ -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
@@ -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
@@ -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).
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+1
-1
Submodule runtime/druntime updated: 590316428b...8b9c6e5d67
+1
-1
Submodule runtime/phobos updated: 8f636073a3...1c80c82684
+1
-1
Submodule tests/d2/dmd-testsuite updated: 2d8d874e2a...99ef349cd4
Reference in New Issue
Block a user