Mercurial > projects > ldc
diff dmd/func.c @ 1630:44b145be2ef5
Merge dmd 1.056.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 06 Feb 2010 15:53:52 +0000 |
parents | 6820110de311 |
children | 9bf06e02070b |
line wrap: on
line diff
--- 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);