Mercurial > projects > ldc
changeset 1630:44b145be2ef5
Merge dmd 1.056.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 06 Feb 2010 15:53:52 +0000 |
parents | b07d683ba4d0 |
children | e16ea850ff81 |
files | dmd/access.c dmd/aggregate.h dmd/arrayop.c dmd/attrib.c dmd/class.c dmd/cond.c dmd/declaration.c dmd/declaration.h dmd/dsymbol.c dmd/dsymbol.h dmd/enum.c dmd/expression.c dmd/expression.h dmd/func.c dmd/identifier.h dmd/inline.c dmd/interpret.c dmd/mangle.c dmd/mars.c dmd/mars.h dmd/module.c dmd/module.h dmd/mtype.c dmd/optimize.c dmd/statement.c dmd/statement.h dmd/struct.c dmd/template.c tests/mini/bug372.d |
diffstat | 29 files changed, 638 insertions(+), 285 deletions(-) [+] |
line wrap: on
line diff
--- a/dmd/access.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/access.c Sat Feb 06 15:53:52 2010 +0000 @@ -392,12 +392,11 @@ #endif if (!e) { - if (d->getModule() != sc->module) - if (d->prot() == PROTprivate || - d->prot() == PROTpackage && !hasPackageAccess(sc, d)) + if (d->prot() == PROTprivate && d->getModule() != sc->module || + d->prot() == PROTpackage && !hasPackageAccess(sc, d)) - error(loc, "%s %s.%s is not accessible from %s", - d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars()); + error(loc, "%s %s.%s is not accessible from %s", + d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars()); } else if (e->type->ty == Tclass) { // Do access check
--- a/dmd/aggregate.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/aggregate.h Sat Feb 06 15:53:52 2010 +0000 @@ -19,9 +19,11 @@ #include "dsymbol.h" +#if IN_LLVM #include <vector> #include <set> #include <map> +#endif struct Identifier; struct Type; @@ -38,6 +40,7 @@ struct VarDeclaration; struct dt_t; +#if IN_LLVM namespace llvm { class Type; @@ -46,6 +49,7 @@ class ConstantStruct; class GlobalVariable; } +#endif struct AggregateDeclaration : ScopeDsymbol {
--- a/dmd/arrayop.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/arrayop.c Sat Feb 06 15:53:52 2010 +0000 @@ -24,6 +24,15 @@ #include "module.h" #include "init.h" +#if IN_DMD +extern int binary(const char *p , const char **tab, int high); + +/************************************** + * Hash table of array op functions already generated or known about. + */ + +StringTable arrayfuncs; +#endif /*********************************** * Construct the array operation expression.
--- a/dmd/attrib.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/attrib.c Sat Feb 06 15:53:52 2010 +0000 @@ -392,6 +392,8 @@ scstc &= ~(STCconst | STCimmutable | STCmanifest); if (stc & (STCgshared | STCshared | STCtls)) scstc &= ~(STCgshared | STCshared | STCtls); + if (stc & (STCsafe | STCtrusted | STCsystem)) + scstc &= ~(STCsafe | STCtrusted | STCsystem); scstc |= stc; setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); @@ -415,6 +417,8 @@ scstc &= ~(STCconst | STCimmutable | STCmanifest); if (stc & (STCgshared | STCshared | STCtls)) scstc &= ~(STCgshared | STCshared | STCtls); + if (stc & (STCsafe | STCtrusted | STCsystem)) + scstc &= ~(STCsafe | STCtrusted | STCsystem); scstc |= stc; semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign); @@ -453,6 +457,10 @@ { STCref, TOKref }, { STCtls, TOKtls }, { STCgshared, TOKgshared }, + { STCproperty, TOKat }, + { STCsafe, TOKat }, + { STCtrusted, TOKat }, + { STCdisable, TOKat }, #endif }; @@ -714,6 +722,8 @@ scope = NULL; } + unsigned dprogress_save = Module::dprogress; + assert(sc->parent); Dsymbol *parent = sc->parent->pastMixin(); @@ -743,7 +753,7 @@ sc = sc->push(); sc->anonAgg = &aad; - sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls); + sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared); sc->inunion = isunion; sc->offset = 0; sc->flags = 0; @@ -775,6 +785,7 @@ scope->setNoFree(); scope->module->addDeferredSemantic(this); } + Module::dprogress = dprogress_save; //printf("\tforward reference %p\n", this); return; } @@ -805,15 +816,15 @@ { VarDeclaration *v = (VarDeclaration *)aad.fields.data[i]; - // LDC +#if IN_LLVM v->offset2 = sc->offset; - +#endif v->offset += sc->offset; - // LDC +#if IN_LLVM if (!v->anonDecl) v->anonDecl = this; - +#endif ad->fields.push(v); } @@ -1369,7 +1380,21 @@ char *name = (char *)mem.malloc(se->len + 1); memcpy(name, se->string, se->len); name[se->len] = 0; +#if OMFOBJ + /* The OMF format allows library names to be inserted + * into the object file. The linker will then automatically + * search that library, too. + */ obj_includelib(name); +#elif ELFOBJ || MACHOBJ + /* 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((void *) name); +#else + error("pragma lib not supported"); +#endif } #if DMDV2 else if (ident == Id::startaddress)
--- a/dmd/class.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/class.c Sat Feb 06 15:53:52 2010 +0000 @@ -264,6 +264,7 @@ scx = scope; // save so we don't make redundant copies scope = NULL; } + unsigned dprogress_save = Module::dprogress; #ifdef IN_GCC methods.setDim(0); #endif @@ -628,6 +629,8 @@ scope->setNoFree(); scope->module->addDeferredSemantic(this); + Module::dprogress = dprogress_save; + //printf("\tsemantic('%s') failed due to forward references\n", toChars()); return; }
--- a/dmd/cond.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/cond.c Sat Feb 06 15:53:52 2010 +0000 @@ -142,10 +142,11 @@ "all", "none", - // LDC +#if IN_LLVM "LLVM", "LDC", "LLVM64", "PPC", "PPC64", "darwin","solaris","freebsd" +#endif }; for (unsigned i = 0; i < sizeof(reserved) / sizeof(reserved[0]); i++)
--- a/dmd/declaration.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/declaration.c Sat Feb 06 15:53:52 2010 +0000 @@ -835,7 +835,7 @@ //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); v->semantic(sc); -/* +#if !IN_LLVM // removed for LDC since TupleDeclaration::toObj already creates the fields; // adding them to the scope again leads to duplicates if (sc->scopesym) @@ -843,7 +843,8 @@ if (sc->scopesym->members) sc->scopesym->members->push(v); } -*/ +#endif + Expression *e = new DsymbolExp(loc, v); exps->data[i] = e; } @@ -1490,9 +1491,10 @@ void TypeInfoDeclaration::semantic(Scope *sc) { assert(linkage == LINKc); - // LDC +#if IN_LLVM if (!global.params.useAvailableExternally) availableExternally = false; +#endif } /***************************** TypeInfoConstDeclaration **********************/
--- a/dmd/declaration.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/declaration.h Sat Feb 06 15:53:52 2010 +0000 @@ -15,9 +15,11 @@ #pragma once #endif /* __DMC__ */ +#if IN_LLVM #include <set> #include <map> #include <string> +#endif #include "dsymbol.h" #include "lexer.h"
--- a/dmd/dsymbol.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/dsymbol.c Sat Feb 06 15:53:52 2010 +0000 @@ -29,7 +29,9 @@ #include "import.h" #include "template.h" #include "attrib.h" +#if IN_LLVM #include "../gen/enums.h" +#endif /****************************** Dsymbol ******************************/
--- a/dmd/dsymbol.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/dsymbol.h Sat Feb 06 15:53:52 2010 +0000 @@ -21,8 +21,9 @@ #include "mars.h" #include "arraytypes.h" -// llvm +#if IN_LLVM #include "../ir/irdsymbol.h" +#endif struct Identifier; struct Scope; @@ -51,6 +52,9 @@ struct NewDeclaration; struct VarDeclaration; struct AttribDeclaration; +#if IN_DMD +struct Symbol; +#endif struct Package; struct Module; struct Import; @@ -76,9 +80,6 @@ #if TARGET_NET struct PragmaScope; #endif -#if IN_DMD -struct Symbol; -#endif #if IN_GCC union tree_node; typedef union tree_node TYPE; @@ -109,6 +110,18 @@ PROTexport, }; +/* State of symbol in winding its way through the passes of the compiler + */ +enum PASS +{ + PASSinit, // initial state + PASSsemantic, // semantic() started + PASSsemanticdone, // semantic() done + PASSsemantic2, // semantic2() run + PASSsemantic3, // semantic3() started + PASSsemantic3done, // semantic3() done + PASSobj, // toObjFile() run +}; struct Dsymbol : Object {
--- a/dmd/enum.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/enum.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -14,6 +14,7 @@ #include "enum.h" #include "mtype.h" #include "scope.h" +#include "module.h" #include "declaration.h" /********************************* EnumDeclaration ****************************/ @@ -74,6 +75,8 @@ scope = NULL; } + unsigned dprogress_save = Module::dprogress; + if (sc->stc & STCdeprecated) isdeprecated = 1; @@ -97,6 +100,7 @@ } isdone = 1; + Module::dprogress++; t = isAnonymous() ? memtype : type; symtab = new DsymbolTable();
--- a/dmd/expression.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/expression.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -3710,7 +3710,6 @@ break; } } - } } else if (thisexp) @@ -8777,8 +8776,11 @@ typeCombine(sc); e1->checkIntegral(); e2 = e2->checkIntegral(); - //e2 = e2->castTo(sc, Type::tshiftcnt); - e2 = e2->castTo(sc, e1->type); // LDC +#if !IN_LLVM + e2 = e2->castTo(sc, Type::tshiftcnt); +#else + e2 = e2->castTo(sc, e1->type); +#endif return this; } @@ -8806,8 +8808,11 @@ typeCombine(sc); e1->checkIntegral(); e2 = e2->checkIntegral(); - //e2 = e2->castTo(sc, Type::tshiftcnt); - e2 = e2->castTo(sc, e1->type); // LDC +#if !IN_LLVM + e2 = e2->castTo(sc, Type::tshiftcnt); +#else + e2 = e2->castTo(sc, e1->type); +#endif return this; } @@ -8835,8 +8840,11 @@ typeCombine(sc); e1->checkIntegral(); e2 = e2->checkIntegral(); - //e2 = e2->castTo(sc, Type::tshiftcnt); - e2 = e2->castTo(sc, e1->type); // LDC +#if !IN_LLVM + e2 = e2->castTo(sc, Type::tshiftcnt); +#else + e2 = e2->castTo(sc, e1->type); +#endif return this; } @@ -9323,8 +9331,11 @@ e1 = e1->checkIntegral(); e2 = e2->checkIntegral(); e1 = e1->integralPromotions(sc); - //e2 = e2->castTo(sc, Type::tshiftcnt); - e2 = e2->castTo(sc, e1->type); // LDC +#if !IN_LLVM + e2 = e2->castTo(sc, Type::tshiftcnt); +#else + e2 = e2->castTo(sc, e1->type); +#endif type = e1->type; } return this; @@ -9348,8 +9359,11 @@ e1 = e1->checkIntegral(); e2 = e2->checkIntegral(); e1 = e1->integralPromotions(sc); - //e2 = e2->castTo(sc, Type::tshiftcnt); - e2 = e2->castTo(sc, e1->type); // LDC +#if !IN_LLVM + e2 = e2->castTo(sc, Type::tshiftcnt); +#else + e2 = e2->castTo(sc, e1->type); +#endif type = e1->type; } return this; @@ -9373,8 +9387,11 @@ e1 = e1->checkIntegral(); e2 = e2->checkIntegral(); e1 = e1->integralPromotions(sc); - //e2 = e2->castTo(sc, Type::tshiftcnt); - e2 = e2->castTo(sc, e1->type); // LDC +#if !IN_LLVM + e2 = e2->castTo(sc, Type::tshiftcnt); +#else + e2 = e2->castTo(sc, e1->type); +#endif type = e1->type; } return this;
--- a/dmd/expression.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/expression.h Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -645,6 +645,7 @@ SymOffExp(Loc loc, Declaration *var, unsigned offset); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); void checkEscape(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int isConst(); @@ -722,6 +723,7 @@ FuncExp(Loc loc, FuncLiteralDeclaration *fd); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); void scanForNestedRef(Scope *sc); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -985,6 +987,7 @@ DelegateExp(Loc loc, Expression *e, FuncDeclaration *func); Expression *semantic(Scope *sc); + Expression *interpret(InterState *istate); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
--- a/dmd/func.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/func.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -65,7 +65,7 @@ inlineNest = 0; inlineAsm = 0; cantInterpret = 0; - semanticRun = 0; + semanticRun = PASSinit; #if DMDV1 nestedFrameRef = 0; #endif @@ -131,8 +131,9 @@ f->fbody = fbody ? fbody->syntaxCopy() : NULL; assert(!fthrows); // deprecated - // LDC +#if IN_LLVM f->intrinsicName = intrinsicName; +#endif return f; } @@ -155,7 +156,7 @@ printf("type: %p, %s\n", type, type->toChars()); #endif - if (semanticRun && isFuncLiteralDeclaration()) + if (semanticRun != PASSinit && isFuncLiteralDeclaration()) { /* Member functions that have return types that are * forward references can have semantic() run more than @@ -164,8 +165,24 @@ */ return; } - assert(semanticRun <= 1); - semanticRun = 1; + parent = sc->parent; + Dsymbol *parent = toParent(); + + if (semanticRun == PASSsemanticdone) + { + if (!parent->isClassDeclaration()) + return; + // need to re-run semantic() in order to set the class's vtbl[] + } + else + { + assert(semanticRun <= PASSsemantic); + semanticRun = PASSsemantic; + } + + unsigned dprogress_save = Module::dprogress; + + foverrides.setDim(0); // reset in case semantic() is being retried for this function if (!type->deco) { @@ -181,15 +198,9 @@ size_t nparams = Parameter::dim(f->parameters); linkage = sc->linkage; -// if (!parent) - { - //parent = sc->scopesym; - parent = sc->parent; - } protection = sc->protection; storage_class |= sc->stc; //printf("function storage_class = x%x\n", storage_class); - Dsymbol *parent = toParent(); if (ident == Id::ctor && !isCtorDeclaration()) error("_ctor is reserved for constructors"); @@ -267,7 +278,7 @@ isInvariantDeclaration() || isUnitTestDeclaration() || isNewDeclaration() || isDelete()) error("special function not allowed in interface %s", id->toChars()); - if (fbody) + if (fbody && isVirtual()) error("function body is not abstract in interface %s", id->toChars()); } @@ -337,8 +348,12 @@ goto Ldone; } - // Find index of existing function in vtbl[] to override - vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0); + /* Find index of existing function in base class's vtbl[] to override + * (the index will be the same as in cd's current vtbl[]) + */ + vi = cd->baseClass ? findVtblIndex(&cd->baseClass->vtbl, cd->baseClass->vtbl.dim) + : -1; + switch (vi) { case -1: @@ -378,10 +393,11 @@ case -2: // can't determine because of fwd refs cd->sizeok = 2; // can't finish due to forward reference + Module::dprogress = dprogress_save; return; default: - { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; + { FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.data[vi]; // This function is covariant with fdv if (fdv->isFinal()) error("cannot override final function %s", fdv->toPrettyChars()); @@ -455,6 +471,7 @@ case -2: cd->sizeok = 2; // can't finish due to forward reference + Module::dprogress = dprogress_save; return; default: @@ -472,19 +489,22 @@ /* Only need to have a tintro if the vptr * offsets differ */ + unsigned errors = global.errors; + global.gag++; // suppress printing of error messages int offset; - if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset)) + int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset); + global.gag--; // suppress printing of error messages + if (errors != global.errors) + { + // any error in isBaseOf() is a forward reference error, so we bail out + global.errors = errors; + cd->sizeok = 2; // can't finish due to forward reference + Module::dprogress = dprogress_save; + return; + } + if (baseOf) { ti = fdv->type; -#if 0 - if (offset) - ti = fdv->type; - else if (type->nextOf()->ty == Tclass) - { ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym; - if (cdn && cdn->sizeok != 1) - ti = fdv->type; - } -#endif } } if (ti) @@ -596,7 +616,7 @@ } } - if (isVirtual()) + if (isVirtual() && semanticRun != PASSsemanticdone) { /* Rewrite contracts as nested functions, then call them. * Doing it as nested functions means that overriding functions @@ -652,6 +672,9 @@ } Ldone: + Module::dprogress++; + semanticRun = PASSsemanticdone; + /* Save scope for possible later use (if we need the * function internals) */ @@ -688,14 +711,14 @@ //printf("\tlinkage = %d\n", sc->linkage); //printf(" sc->incontract = %d\n", sc->incontract); - if (semanticRun >= 3) + if (semanticRun >= PASSsemantic3) return; - semanticRun = 3; - - // LDC + semanticRun = PASSsemantic3; + +#if IN_LLVM if (!global.params.useAvailableExternally) availableExternally = false; - +#endif if (!type || type->ty != Tfunction) return; f = (TypeFunction *)(type); @@ -1466,7 +1489,7 @@ sc2->callSuper = 0; sc2->pop(); } - semanticRun = 4; + semanticRun = PASSsemantic3done; } void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -1638,6 +1661,7 @@ /************************************************* * Find index of function in vtbl[0..dim] that * this function overrides. + * Prefer an exact match to a covariant one. * Returns: * -1 didn't find one * -2 can't determine because of forward references @@ -1645,11 +1669,16 @@ int FuncDeclaration::findVtblIndex(Array *vtbl, int dim) { + FuncDeclaration *mismatch = NULL; + int bestvi = -1; for (int vi = 0; vi < dim; vi++) { FuncDeclaration *fdv = ((Dsymbol *)vtbl->data[vi])->isFuncDeclaration(); if (fdv && fdv->ident == ident) { + if (type->equals(fdv->type)) // if exact match + return vi; // no need to look further + int cov = type->covariant(fdv->type); //printf("\tbaseclass cov = %d\n", cov); switch (cov) @@ -1658,15 +1687,12 @@ break; case 1: - return vi; + bestvi = vi; // covariant, but not identical + break; // keep looking for an exact match case 2: - //type->print(); - //fdv->type->print(); - //printf("%s %s\n", type->deco, fdv->type->deco); - error("of type %s overrides but is not covariant with %s of type %s", - type->toChars(), fdv->toPrettyChars(), fdv->type->toChars()); - break; + mismatch = fdv; // overrides, but is not covariant + break; // keep looking for an exact match case 3: return -2; // forward references @@ -1676,7 +1702,15 @@ } } } - return -1; + if (bestvi == -1 && mismatch) + { + //type->print(); + //mismatch->type->print(); + //printf("%s %s\n", type->deco, mismatch->type->deco); + error("of type %s overrides but is not covariant with %s of type %s", + type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars()); + } + return bestvi; } /**************************************************** @@ -2554,7 +2588,7 @@ id = "__dgliteral"; else id = "__funcliteral"; - this->ident = Identifier::generateId(id); + this->ident = Lexer::uniqueId(id); this->tok = tok; this->fes = fes; //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars()); @@ -2568,7 +2602,9 @@ if (s) f = (FuncLiteralDeclaration *)s; else - f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes); + { f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes); + f->ident = ident; // keep old identifier + } FuncDeclaration::syntaxCopy(f); return f; } @@ -2634,19 +2670,14 @@ void CtorDeclaration::semantic(Scope *sc) { - ClassDeclaration *cd; - Type *tret; - - //printf("CtorDeclaration::semantic()\n"); - if (type) - return; - + //printf("CtorDeclaration::semantic() %s\n", toChars()); sc = sc->push(); sc->stc &= ~STCstatic; // not a static constructor parent = sc->parent; Dsymbol *parent = toParent(); - cd = parent->isClassDeclaration(); + Type *tret; + ClassDeclaration *cd = parent->isClassDeclaration(); if (!cd) { error("constructors are only for class definitions"); @@ -2655,7 +2686,8 @@ } else tret = cd->type; //->referenceTo(); - type = new TypeFunction(arguments, tret, varargs, LINKd); + if (!type) + type = new TypeFunction(arguments, tret, varargs, LINKd); #if STRUCTTHISREF if (ad && ad->isStructDeclaration()) ((TypeFunction *)type)->isref = 1; @@ -2670,7 +2702,7 @@ // Append: // return this; // to the function body - if (fbody) + if (fbody && semanticRun < PASSsemantic) { Expression *e = new ThisExp(loc); Statement *s = new ReturnStatement(loc, e); @@ -2744,6 +2776,7 @@ { //printf("PostBlitDeclaration::semantic() %s\n", toChars()); //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor); + //printf("stc = x%llx\n", sc->stc); parent = sc->parent; Dsymbol *parent = toParent(); StructDeclaration *ad = parent->isStructDeclaration(); @@ -2751,9 +2784,11 @@ { error("post blits are only for struct/union definitions, not %s %s", parent->kind(), parent->toChars()); } - else if (ident == Id::_postblit) + else if (ident == Id::_postblit && semanticRun < PASSsemantic) ad->postblits.push(this); - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + + if (!type) + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); sc = sc->push(); sc->stc &= ~STCstatic; // not static @@ -2786,9 +2821,7 @@ void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - if (hgs->hdrgen) - return; - buf->writestring("=this()"); + buf->writestring("this(this)"); bodyToCBuffer(buf, hgs); } #endif @@ -2825,9 +2858,11 @@ error("destructors are only for class/struct/union definitions, not %s %s", parent->kind(), parent->toChars()); fatal(); } - else + else if (semanticRun < PASSsemantic) cd->dtors.push(this); - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + + if (!type) + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); sc = sc->push(); sc->stc &= ~STCstatic; // not a static destructor @@ -2893,10 +2928,8 @@ Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s) { - StaticCtorDeclaration *scd; - assert(!s); - scd = new StaticCtorDeclaration(loc, endloc); + StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc); return FuncDeclaration::syntaxCopy(scd); } @@ -2905,13 +2938,14 @@ { //printf("StaticCtorDeclaration::semantic()\n"); - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + if (!type) + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); /* If the static ctor appears within a template instantiation, * it could get called multiple times by the module constructors * for different modules. Thus, protect it with a gate. */ - if (inTemplateInstance()) + if (inTemplateInstance() && semanticRun < PASSsemantic) { /* Add this prefix to the function: * static int gate; @@ -2943,6 +2977,7 @@ m = sc->module; if (m) { m->needmoduleinfo = 1; + //printf("module1 %s needs moduleinfo\n", m->toChars()); #ifdef IN_GCC m->strictlyneedmoduleinfo = 1; #endif @@ -3005,20 +3040,16 @@ void StaticDtorDeclaration::semantic(Scope *sc) { - ClassDeclaration *cd; - Type *tret; - - cd = sc->scopesym->isClassDeclaration(); - if (!cd) - { - } - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + ClassDeclaration *cd = sc->scopesym->isClassDeclaration(); + + if (!type) + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); /* If the static ctor appears within a template instantiation, * it could get called multiple times by the module constructors * for different modules. Thus, protect it with a gate. */ - if (inTemplateInstance()) + if (inTemplateInstance() && semanticRun < PASSsemantic) { /* Add this prefix to the function: * static int gate; @@ -3112,23 +3143,21 @@ void InvariantDeclaration::semantic(Scope *sc) { - AggregateDeclaration *ad; - Type *tret; - parent = sc->parent; Dsymbol *parent = toParent(); - ad = parent->isAggregateDeclaration(); + AggregateDeclaration *ad = parent->isAggregateDeclaration(); if (!ad) { error("invariants are only for struct/union/class definitions"); return; } - else if (ad->inv && ad->inv != this) + else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic) { error("more than one invariant for %s", ad->toChars()); } ad->inv = this; - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + if (!type) + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); sc = sc->push(); sc->stc &= ~STCstatic; // not a static invariant @@ -3195,7 +3224,8 @@ { if (global.params.useUnitTests) { - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + if (!type) + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); Scope *sc2 = sc->push(); sc2->linkage = LINKd; FuncDeclaration::semantic(sc2); @@ -3271,20 +3301,18 @@ void NewDeclaration::semantic(Scope *sc) { - ClassDeclaration *cd; - Type *tret; - //printf("NewDeclaration::semantic()\n"); parent = sc->parent; Dsymbol *parent = toParent(); - cd = parent->isClassDeclaration(); + ClassDeclaration *cd = parent->isClassDeclaration(); if (!cd && !parent->isStructDeclaration()) { error("new allocators only are for class or struct definitions"); } - tret = Type::tvoid->pointerTo(); - type = new TypeFunction(arguments, tret, varargs, LINKd); + Type *tret = Type::tvoid->pointerTo(); + if (!type) + type = new TypeFunction(arguments, tret, varargs, LINKd); type = type->semantic(loc, sc); assert(type->ty == Tfunction); @@ -3357,18 +3385,17 @@ void DeleteDeclaration::semantic(Scope *sc) { - ClassDeclaration *cd; - //printf("DeleteDeclaration::semantic()\n"); parent = sc->parent; Dsymbol *parent = toParent(); - cd = parent->isClassDeclaration(); + ClassDeclaration *cd = parent->isClassDeclaration(); if (!cd && !parent->isStructDeclaration()) { error("new allocators only are for class or struct definitions"); } - type = new TypeFunction(arguments, Type::tvoid, 0, LINKd); + if (!type) + type = new TypeFunction(arguments, Type::tvoid, 0, LINKd); type = type->semantic(loc, sc); assert(type->ty == Tfunction);
--- a/dmd/identifier.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/identifier.h Sat Feb 06 15:53:52 2010 +0000 @@ -16,11 +16,12 @@ #endif /* __DMC__ */ #include "root.h" - +#if IN_LLVM namespace llvm { class Value; } +#endif struct Identifier : Object {
--- a/dmd/inline.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/inline.c Sat Feb 06 15:53:52 2010 +0000 @@ -1281,7 +1281,7 @@ if (needThis() && !hasthis) return 0; - if (inlineNest || (semanticRun < 3 && !hdrscan)) + if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan)) { #if CANINLINE_LOG printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
--- a/dmd/interpret.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/interpret.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -52,6 +52,8 @@ Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd); Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd); +ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim); + /************************************* * Attempt to interpret a function given the arguments. * Input: @@ -92,7 +94,7 @@ } #endif - if (cantInterpret || semanticRun == 3) + if (cantInterpret || semanticRun == PASSsemantic3) return NULL; if (!fbody) @@ -100,13 +102,13 @@ return NULL; } - if (semanticRun < 3 && scope) + if (semanticRun < PASSsemantic3 && scope) { semantic3(scope); if (global.errors) // if errors compiling this function return NULL; } - if (semanticRun < 4) + if (semanticRun < PASSsemantic3done) return NULL; Type *tb = type->toBasetype(); @@ -160,7 +162,7 @@ { Expression *earg = (Expression *)arguments->data[i]; Parameter *arg = Parameter::getNth(tf->parameters, i); - if (arg->storageClass & (STCout | STCref)) + if (arg->storageClass & (STCout | STCref | STClazy)) { } else @@ -1005,6 +1007,35 @@ return this; } +Expression *FuncExp::interpret(InterState *istate) +{ +#if LOG + printf("FuncExp::interpret() %s\n", toChars()); +#endif + return this; +} + +Expression *SymOffExp::interpret(InterState *istate) +{ +#if LOG + printf("SymOffExp::interpret() %s\n", toChars()); +#endif + if (var->isFuncDeclaration() && offset == 0) + { + return this; + } + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; +} + +Expression *DelegateExp::interpret(InterState *istate) +{ +#if LOG + printf("DelegateExp::interpret() %s\n", toChars()); +#endif + return this; +} + Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) { Expression *e = EXP_CANT_INTERPRET; @@ -1013,6 +1044,11 @@ if (v) { #if DMDV2 + /* Magic variable __ctfe always returns true when interpreting + */ + if (v->ident == Id::ctfe) + return new IntegerExp(loc, 1, Type::tbool); + if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) #else if (v->isConst() && v->init) @@ -1021,6 +1057,16 @@ if (e && !e->type) e->type = v->type; } + else if (v->isCTFE() && !v->value) + { + if (v->init) + { + e = v->init->toExpression(); + e = e->interpret(istate); + } + else // This should never happen + e = v->type->defaultInitLiteral(); + } else { e = v->value; if (!v->isCTFE()) @@ -1482,7 +1528,7 @@ } /*************************************** - * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$] + * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint+newelems.length..$] */ Expressions *spliceElements(Expressions *oldelems, Expressions *newelems, size_t insertpoint) @@ -1499,6 +1545,26 @@ return expsx; } +/*************************************** + * Returns oldstr[0..insertpoint] ~ newstr ~ oldstr[insertpoint+newlen..$] + */ +StringExp *spliceStringExp(StringExp *oldstr, StringExp *newstr, size_t insertpoint) +{ + assert(oldstr->sz==newstr->sz); + unsigned char *s; + size_t oldlen = oldstr->len; + size_t newlen = newstr->len; + size_t sz = oldstr->sz; + s = (unsigned char *)mem.calloc(oldlen + 1, sz); + memcpy(s, oldstr->string, oldlen * sz); + memcpy(s + insertpoint * sz, newstr->string, newlen * sz); + StringExp *se2 = new StringExp(oldstr->loc, s, oldlen); + se2->committed = oldstr->committed; + se2->postfix = oldstr->postfix; + se2->type = oldstr->type; + return se2; +} + /****************************** * Create an array literal consisting of 'elem' duplicated 'dim' times. */ @@ -1514,6 +1580,28 @@ return ae; } +/****************************** + * Create a string literal consisting of 'value' duplicated 'dim' times. + */ +StringExp *createBlockDuplicatedStringLiteral(Type *type, + unsigned value, size_t dim, int sz) +{ + unsigned char *s; + s = (unsigned char *)mem.calloc(dim + 1, sz); + for (int elemi=0; elemi<dim; ++elemi) + { + switch (sz) + { + case 1: s[elemi] = value; break; + case 2: ((unsigned short *)s)[elemi] = value; break; + case 4: ((unsigned *)s)[elemi] = value; break; + default: assert(0); + } + } + StringExp *se = new StringExp(0, s, dim); + se->type = type; + return se; +} /******************************** * Add v to the istate list, unless it already exists there. @@ -1582,13 +1670,16 @@ // To reduce code complexity of handling dotvar expressions, // extract the aggregate now. Expression *aggregate; - if (e1->op == TOKdotvar) { + if (e1->op == TOKdotvar) + { aggregate = ((DotVarExp *)e1)->e1; // Get rid of 'this'. if (aggregate->op == TOKthis && istate->localThis) - aggregate = istate->localThis; + aggregate = istate->localThis; } - + if (e1->op == TOKthis && istate->localThis) + e1 = istate->localThis; + /* Assignment to variable of the form: * v = e2 */ @@ -1623,7 +1714,8 @@ if (e2 == EXP_CANT_INTERPRET) return e2; - addVarToInterstate(istate, v); + if (istate) + addVarToInterstate(istate, v); v->value = e2; e = Cast(type, type, post ? ev : e2); } @@ -1668,16 +1760,21 @@ * on the void value - to do that we'd need a VoidExp. * That's probably a good enhancement idea. */ - v->value = v->type->defaultInit(); + v->value = v->type->defaultInitLiteral(); } Expression *vie = v->value; + assert(vie != EXP_CANT_INTERPRET); + if (vie->op == TOKvar) { Declaration *d = ((VarExp *)vie)->var; vie = getVarExp(e1->loc, istate, d); } if (vie->op != TOKstructliteral) + { + error("Cannot assign %s=%s in CTFE", v->toChars(), vie->toChars()); return EXP_CANT_INTERPRET; + } StructLiteralExp *se = (StructLiteralExp *)vie; VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration(); if (!vf) @@ -2015,19 +2112,19 @@ error("%s cannot be modified at compile time", v->toChars()); return EXP_CANT_INTERPRET; } - // Chase down rebinding of out and ref - if (v->value && v->value->op == TOKvar) - { - VarExp *ve2 = (VarExp *)v->value; - if (ve2->var->isStaticStructInitDeclaration()) - { // This can happen if v is a struct initialized to - // 0 using an __initZ SymbolDeclaration from - // TypeStruct::defaultInit() - } - else - v = ve2->var->isVarDeclaration(); - assert(v); + // Chase down rebinding of out and ref + if (v->value && v->value->op == TOKvar) + { + VarExp *ve2 = (VarExp *)v->value; + if (ve2->var->isStaticStructInitDeclaration()) + { // This can happen if v is a struct initialized to + // 0 using an __initZ SymbolDeclaration from + // TypeStruct::defaultInit() } + else + v = ve2->var->isVarDeclaration(); + assert(v); + } /* Set the $ variable */ Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) @@ -2062,10 +2159,7 @@ if (v->value->op == TOKarrayliteral) dim = ((ArrayLiteralExp *)v->value)->elements->dim; else if (v->value->op ==TOKstring) - { - error("String slice assignment is not yet supported in CTFE"); - return EXP_CANT_INTERPRET; - } + dim = ((StringExp *)v->value)->len; } else { @@ -2075,69 +2169,89 @@ int upperbound = upper ? upper->toInteger() : dim; int lowerbound = lower ? lower->toInteger() : 0; - ArrayLiteralExp *existing; if (((int)lowerbound < 0) || (upperbound > dim)) { - error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); + error("Array bounds [0..%d] exceeded in slice [%d..%d]", + dim, lowerbound, upperbound); return EXP_CANT_INTERPRET; } - if (upperbound-lowerbound != dim) + // Could either be slice assignment (v[] = e[]), + // or block assignment (v[] = val). + // For the former, we check that the lengths match. + bool isSliceAssignment = (e2->op == TOKarrayliteral) + || (e2->op == TOKstring); + size_t srclen = 0; + if (e2->op == TOKarrayliteral) + srclen = ((ArrayLiteralExp *)e2)->elements->dim; + else if (e2->op == TOKstring) + srclen = ((StringExp *)e2)->len; + if (isSliceAssignment && srclen != (upperbound - lowerbound)) { - // Only modifying part of the array. Must create a new array literal. - // If the existing array is uninitialized (this can only happen - // with static arrays), create it. - if (v->value && v->value->op == TOKarrayliteral) - existing = (ArrayLiteralExp *)v->value; - else - { - // this can only happen with static arrays - existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); - } + error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); + return e; } - if (e2->op == TOKarrayliteral) { // Static array assignment from literal ArrayLiteralExp *ae = (ArrayLiteralExp *)e2; - if (ae->elements->dim != (upperbound - lowerbound)) - { - error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound); - return e; - } if (upperbound - lowerbound == dim) v->value = ae; else { + ArrayLiteralExp *existing; + // Only modifying part of the array. Must create a new array literal. + // If the existing array is uninitialized (this can only happen + // with static arrays), create it. + if (v->value && v->value->op == TOKarrayliteral) + existing = (ArrayLiteralExp *)v->value; + else // this can only happen with static arrays + existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); // value[] = value[0..lower] ~ ae ~ value[upper..$] existing->elements = spliceElements(existing->elements, ae->elements, lowerbound); v->value = existing; } return e2; } + else if (e2->op == TOKstring) + { + StringExp *se = (StringExp *)e2; + if (upperbound-lowerbound == dim) + v->value = e2; + else + { + if (!v->value) + v->value = createBlockDuplicatedStringLiteral(se->type, + se->type->defaultInit()->toInteger(), dim, se->sz); + if (v->value->op==TOKstring) + v->value = spliceStringExp((StringExp *)v->value, se, lowerbound); + else + error("String slice assignment is not yet supported in CTFE"); + } + return e2; + } else if (t->nextOf()->ty == e2->type->ty) { - // Static array block assignment - if (upperbound-lowerbound ==dim) + // Static array block assignment + if (upperbound - lowerbound == dim) v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim); else { + ArrayLiteralExp *existing; + // Only modifying part of the array. Must create a new array literal. + // If the existing array is uninitialized (this can only happen + // with static arrays), create it. + if (v->value && v->value->op == TOKarrayliteral) + existing = (ArrayLiteralExp *)v->value; + else // this can only happen with static arrays + existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim); // value[] = value[0..lower] ~ ae ~ value[upper..$] - existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound); + existing->elements = spliceElements(existing->elements, + createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, + lowerbound); v->value = existing; } return e2; } - else if (e2->op == TOKstring) - { - StringExp *se = (StringExp *)e2; - // This is problematic. char[8] should be storing - // values as a string literal, not - // as an array literal. Then, for static arrays, we - // could do modifications - // in-place, with a dramatic memory and speed improvement. - error("String slice assignment is not yet supported in CTFE"); - return e2; - } else { error("Slice operation %s cannot be evaluated at compile time", toChars()); @@ -2260,74 +2374,118 @@ #if LOG printf("CallExp::interpret() %s\n", toChars()); #endif - if (e1->op == TOKdotvar) + + Expression * pthis = NULL; + FuncDeclaration *fd = NULL; + Expression *ecall = e1; + if (ecall->op == TOKindex) + ecall = e1->interpret(istate); + if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration()) + ecall = e1->interpret(istate); + + if (ecall->op == TOKdotvar) + { // Calling a member function + pthis = ((DotVarExp*)e1)->e1; + fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); + } + else if (ecall->op == TOKvar) { - Expression * pthis = ((DotVarExp*)e1)->e1; - FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); - TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; - if (tf) - { // Member function call - if(pthis->op == TOKthis) - pthis = istate->localThis; - Expression *eresult = fd->interpret(istate, arguments, pthis); + VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration(); + if (vd && vd->value) + ecall = vd->value; + else // Calling a function + fd = ((VarExp *)e1)->var->isFuncDeclaration(); + } + if (ecall->op == TOKdelegate) + { // Calling a delegate + fd = ((DelegateExp *)ecall)->func; + pthis = ((DelegateExp *)ecall)->e1; + } + else if (ecall->op == TOKfunction) + { // Calling a delegate literal + fd = ((FuncExp*)ecall)->fd; + } + else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKfunction) + { // Calling a function literal + fd = ((FuncExp*)((PtrExp*)ecall)->e1)->fd; + } + else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKvar) + { // Calling a function pointer + VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration(); + if (vd && vd->value && vd->value->op==TOKsymoff) + fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration(); + } + + TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; + if (!tf) + { // DAC: I'm not sure if this ever happens + //printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall); + error("cannot evaluate %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + if (pthis && fd) + { // Member function call + if (pthis->op == TOKthis) + pthis = istate->localThis; + else if (pthis->op == TOKcomma) + pthis = pthis->interpret(istate); + Expression *eresult = fd->interpret(istate, arguments, pthis); + if (eresult) + e = eresult; + else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) + e = EXP_VOID_INTERPRET; + else + error("cannot evaluate %s at compile time", toChars()); + return e; + } + else if (fd) + { // function call +#if DMDV2 + enum BUILTIN b = fd->isBuiltin(); + if (b) + { Expressions args; + args.setDim(arguments->dim); + for (size_t i = 0; i < args.dim; i++) + { + Expression *earg = (Expression *)arguments->data[i]; + earg = earg->interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return earg; + args.data[i] = (void *)earg; + } + e = eval_builtin(b, &args); + if (!e) + e = EXP_CANT_INTERPRET; + } + else +#endif + // Inline .dup + if (fd->ident == Id::adDup && arguments && arguments->dim == 2) + { + e = (Expression *)arguments->data[1]; + e = e->interpret(istate); + if (e != EXP_CANT_INTERPRET) + { + e = expType(type, e); + } + } + else + { + Expression *eresult = fd->interpret(istate, arguments); if (eresult) e = eresult; else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) e = EXP_VOID_INTERPRET; else error("cannot evaluate %s at compile time", toChars()); - return e; - } + } + } + else + { error("cannot evaluate %s at compile time", toChars()); return EXP_CANT_INTERPRET; } - if (e1->op == TOKvar) - { - FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); - if (fd) - { -#if DMDV2 - enum BUILTIN b = fd->isBuiltin(); - if (b) - { Expressions args; - args.setDim(arguments->dim); - for (size_t i = 0; i < args.dim; i++) - { - Expression *earg = (Expression *)arguments->data[i]; - earg = earg->interpret(istate); - if (earg == EXP_CANT_INTERPRET) - return earg; - args.data[i] = (void *)earg; - } - e = eval_builtin(b, &args); - if (!e) - e = EXP_CANT_INTERPRET; - } - else -#endif - // Inline .dup - if (fd->ident == Id::adDup && arguments && arguments->dim == 2) - { - e = (Expression *)arguments->data[1]; - e = e->interpret(istate); - if (e != EXP_CANT_INTERPRET) - { - e = expType(type, e); - } - } - else - { - Expression *eresult = fd->interpret(istate, arguments); - if (eresult) - e = eresult; - else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) - e = EXP_VOID_INTERPRET; - else - error("cannot evaluate %s at compile time", toChars()); - } - } - } - return e; + return e; } Expression *CommaExp::interpret(InterState *istate) @@ -2335,6 +2493,21 @@ #if LOG printf("CommaExp::interpret() %s\n", toChars()); #endif + // If the comma returns a temporary variable, it needs to be an lvalue + // (this is particularly important for struct constructors) + if (e1->op == TOKdeclaration && e2->op == TOKvar + && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var) + { + VarExp* ve = (VarExp *)e2; + VarDeclaration *v = ve->var->isVarDeclaration(); + if (!v->init && !v->value) + v->value = v->type->defaultInitLiteral(); + if (!v->value) + v->value = v->init->toExpression(); + v->value = v->value->interpret(istate); + return e2; + } + Expression *e = e1->interpret(istate); if (e != EXP_CANT_INTERPRET) e = e2->interpret(istate); @@ -2516,14 +2689,18 @@ if( this->e1->op == TOKaddress) { // Special case: deal with compiler-inserted assert(&this, "null this") AddrExp *ade = (AddrExp *)this->e1; - if(ade->e1->op == TOKthis && istate->localThis) - return istate->localThis->interpret(istate); + if (ade->e1->op == TOKthis && istate->localThis) + if (ade->e1->op == TOKdotvar + && ((DotVarExp *)(istate->localThis))->e1->op == TOKthis) + return getVarExp(loc, istate, ((DotVarExp*)(istate->localThis))->var); + else + return istate->localThis->interpret(istate); } -if (this->e1->op == TOKthis) -{ - if(istate->localThis) - return istate->localThis->interpret(istate); -} + if (this->e1->op == TOKthis) + { + if (istate->localThis) + return istate->localThis->interpret(istate); + } e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant;
--- a/dmd/mangle.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/mangle.c Sat Feb 06 15:53:52 2010 +0000 @@ -113,9 +113,9 @@ case LINKd: break; - // LDC +#if IN_LLVM case LINKintrinsic: - +#endif case LINKc: case LINKwindows: case LINKpascal:
--- a/dmd/mars.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/mars.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -13,8 +13,10 @@ #include <ctype.h> #include <assert.h> #include <limits.h> +#if IN_LLVM #include <string> #include <cstdarg> +#endif #if POSIX #include <errno.h> @@ -34,7 +36,9 @@ #include "lexer.h" #include "json.h" +#if IN_LLVM #include "gen/revisions.h" +#endif Global global; @@ -46,6 +50,7 @@ doc_ext = "html"; ddoc_ext = "ddoc"; json_ext = "json"; + map_ext = "map"; // LDC ll_ext = "ll"; @@ -58,7 +63,7 @@ copyright = "Copyright (c) 1999-2009 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.055"; + version = "v1.056"; ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; global.structalign = 8;
--- a/dmd/mars.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/mars.h Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -235,7 +235,9 @@ char *deffile; char *resfile; char *exefile; + char *mapfile; +#if IN_LLVM // LDC stuff OUTPUTFLAG output_ll; OUTPUTFLAG output_bc; @@ -250,6 +252,7 @@ const char* llvmArch; const char *targetTriple; const char *dataLayout; +#endif }; struct Global @@ -268,6 +271,7 @@ const char *ddoc_ext; // for Ddoc macro include files const char *hdr_ext; // for D 'header' import files const char *json_ext; // for JSON files + const char *map_ext; // for .map files const char *copyright; const char *written; Array *path; // Array of char*'s which form the import lookup path @@ -393,8 +397,9 @@ LINKwindows, LINKpascal, - // LDC +#if IN_LLVM LINKintrinsic, +#endif }; enum DYNCAST
--- a/dmd/module.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/module.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -44,7 +44,7 @@ #include "d-dmd-gcc.h" #endif - +#if IN_LLVM #include "llvm/Support/CommandLine.h" #include <map> @@ -55,8 +55,7 @@ static llvm::cl::opt<bool> fqnNames("oq", llvm::cl::desc("Write object files with fully qualified names"), llvm::cl::ZeroOrMore); - - +#endif ClassDeclaration *Module::moduleinfo; @@ -971,7 +970,8 @@ void Module::runDeferredSemantic() { - size_t len; + if (dprogress == 0) + return; static int nested; if (nested) @@ -979,6 +979,7 @@ //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); nested++; + size_t len; do { dprogress = 0;
--- a/dmd/module.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/module.h Sat Feb 06 15:53:52 2010 +0000 @@ -153,7 +153,7 @@ Dsymbol *symtabInsert(Dsymbol *s); void deleteObjFile(); void addDeferredSemantic(Dsymbol *s); - void runDeferredSemantic(); + static void runDeferredSemantic(); int imports(Module *m); // Back end
--- a/dmd/mtype.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/mtype.c Sat Feb 06 15:53:52 2010 +0000 @@ -4061,8 +4061,15 @@ Type *TypeEnum::toBasetype() { if (sym->scope) - { - sym->semantic(NULL); // attempt to resolve forward reference + { // Enum is forward referenced. We don't need to resolve the whole thing, + // just the base type + if (sym->memtype) + { sym->memtype = sym->memtype->semantic(sym->loc, sym->scope); + } + else + { if (!sym->isAnonymous()) + sym->memtype = Type::tint32; + } } if (!sym->memtype) {
--- a/dmd/optimize.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/optimize.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -344,7 +344,9 @@ } Expression *CallExp::optimize(int result) -{ Expression *e = this; +{ + //printf("CallExp::optimize(result = %d) %s\n", result, toChars()); + Expression *e = this; // Optimize parameters if (arguments) @@ -358,17 +360,15 @@ } e1 = e1->optimize(result); - if (e1->op == TOKvar && result & WANTinterpret) + if (result & WANTinterpret) { - FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); - if (fd) - { - Expression *eresult = fd->interpret(NULL, arguments); - if (eresult && eresult != EXP_VOID_INTERPRET) - e = eresult; - else if (result & WANTinterpret) - error("cannot evaluate %s at compile time", toChars()); - } + Expression *eresult = interpret(NULL); + if (eresult == EXP_CANT_INTERPRET) + return e; + if (eresult && eresult != EXP_VOID_INTERPRET) + e = eresult; + else + error("cannot evaluate %s at compile time", toChars()); } return e; } @@ -624,6 +624,22 @@ { Expression *e; //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); + // Comma needs special treatment, because it may + // contain compiler-generated declarations. We can interpret them, but + // otherwise we must NOT attempt to constant-fold them. + // In particular, if the comma returns a temporary variable, it needs + // to be an lvalue (this is particularly important for struct constructors) + + if (result & WANTinterpret) + { // Interpreting comma needs special treatment, because it may + // contain compiler-generated declarations. + e = interpret(NULL); + return (e == EXP_CANT_INTERPRET) ? this : e; + } + // Don't constant fold if it is a compiler-generated temporary. + if (e1->op == TOKdeclaration) + return this; + e1 = e1->optimize(result & WANTinterpret); e2 = e2->optimize(result); if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) @@ -709,8 +725,8 @@ { if (e1->op == TOKstring) { // Convert slice of string literal into dynamic array Type *t = e1->type->toBasetype(); - if (t->next) - e = e1->castTo(NULL, t->next->arrayOf()); + if (t->nextOf()) + e = e1->castTo(NULL, t->nextOf()->arrayOf()); } return e; }
--- a/dmd/statement.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/statement.c Sat Feb 06 15:53:52 2010 +0000 @@ -2483,7 +2483,14 @@ Expression *e = (Expression *)args->data[i]; e = e->semantic(sc); +#if 1 e = e->optimize(WANTvalue | WANTinterpret); +#else + e = e->interpret(NULL); + if (e == EXP_CANT_INTERPRET) + fprintf(stdmsg, ((Expression *)args->data[i])->toChars()); + else +#endif if (e->op == TOKstring) { StringExp *se = (StringExp *)e;
--- a/dmd/statement.h Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/statement.h Sat Feb 06 15:53:52 2010 +0000 @@ -54,13 +54,14 @@ struct SynchronizedStatement; enum TOK; - +#if IN_LLVM namespace llvm { class Value; class BasicBlock; class ConstantInt; } +#endif // Back end struct IRState; @@ -141,9 +142,10 @@ virtual IfStatement *isIfStatement() { return NULL; } virtual CaseStatement* isCaseStatement() { return NULL; } - // LDC +#if IN_LLVM virtual void toNakedIR(IRState *irs); virtual AsmBlockStatement* endsWithAsm(); +#endif }; struct PeelStatement : Statement @@ -172,8 +174,9 @@ void toIR(IRState *irs); - // LDC +#if IN_LLVM void toNakedIR(IRState *irs); +#endif }; struct CompileStatement : Statement
--- a/dmd/struct.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/struct.c Sat Feb 06 15:53:52 2010 +0000 @@ -19,6 +19,7 @@ #include "module.h" #include "id.h" #include "statement.h" +#include "template.h" /********************************* AggregateDeclaration ****************************/ @@ -269,6 +270,8 @@ scope = NULL; } + unsigned dprogress_save = Module::dprogress; + parent = sc->parent; type = type->semantic(loc, sc); #if STRUCTTHISREF @@ -417,6 +420,8 @@ scope = scx ? scx : new Scope(*sc); scope->setNoFree(); scope->module->addDeferredSemantic(this); + + Module::dprogress = dprogress_save; //printf("\tdeferring %s\n", toChars()); return; }
--- a/dmd/template.c Wed Jan 06 19:53:35 2010 +0100 +++ b/dmd/template.c Sat Feb 06 15:53:52 2010 +0000 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -3539,7 +3539,8 @@ error("error instantiating"); if (tinst) { tinst->printInstantiationTrace(); - fatal(); + if (!global.gag) + fatal(); } errors = 1; if (global.gag)