Mercurial > projects > ddmd
diff dmd/FuncDeclaration.d @ 179:cd48cb899aee
Updated to dmd2.040
author | korDen |
---|---|
date | Sun, 17 Oct 2010 20:56:07 +0400 |
parents | e3afd1303184 |
children | b0d41ff5e0df |
line wrap: on
line diff
--- a/dmd/FuncDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/FuncDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -6,6 +6,7 @@ import dmd.AddrExp; import dmd.TryFinallyStatement; import dmd.TryCatchStatement; +import dmd.SharedStaticDtorDeclaration; import dmd.Catch; import dmd.DeclarationStatement; import dmd.StaticDtorDeclaration; @@ -20,6 +21,7 @@ import dmd.Id; import dmd.StorageClassDeclaration; import dmd.StringExp; +import dmd.PASS; import dmd.DsymbolExp; import dmd.HaltExp; import dmd.CommaExp; @@ -27,6 +29,7 @@ import dmd.IntegerExp; import dmd.ExpStatement; import dmd.CSX; +import dmd.PROT; import dmd.CompoundStatement; import dmd.LabelStatement; import dmd.ThisExp; @@ -150,19 +153,15 @@ Dsymbols parameters; // Array of VarDeclaration's for parameters DsymbolTable labtab; // statement label symbol table Declaration overnext; // next in overload list - Loc endloc; // location of closing curly bracket - int vtblIndex; // for member functions, index into vtbl[] - int naked; // !=0 if naked - int inlineAsm; // !=0 if has inline assembler + Loc endloc; // location of closing curly bracket + int vtblIndex; // for member functions, index into vtbl[] + int naked; // !=0 if naked + int inlineAsm; // !=0 if has inline assembler ILS inlineStatus; - int inlineNest; // !=0 if nested inline + int inlineNest; // !=0 if nested inline int cantInterpret; // !=0 if cannot interpret function - int semanticRun; // 1 semantic() run - // 2 semantic2() run - // 3 semantic3() started - // 4 semantic3() done - // 5 toObjFile() run - // this function's frame ptr + PASS semanticRun; + // this function's frame ptr ForeachStatement fes; // if foreach body, this is the foreach int introducing; // !=0 if 'introducing' function Type tintro; // if !=null, then this is the type @@ -231,7 +230,7 @@ inlineNest = 0; inlineAsm = 0; cantInterpret = 0; - semanticRun = 0; + semanticRun = PASSinit; version (DMDV1) { nestedFrameRef = 0; } @@ -291,7 +290,7 @@ printf("type: %p, %s\n", type, type.toChars()); } - if (semanticRun && isFuncLiteralDeclaration()) + if (semanticRun != PASSinit && isFuncLiteralDeclaration()) { /* Member functions that have return types that are * forward references can have semantic() run more than @@ -300,18 +299,35 @@ */ 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; + } + + uint dprogress_save = global.dprogress; + + foverrides.setDim(0); // reset in case semantic() is being retried for this function storage_class |= sc.stc & ~STC.STCref; - //printf("function storage_class = x%x\n", storage_class); + //printf("function storage_class = x%llx, sc->stc = x%llx\n", storage_class, sc->stc); if (!originalType) originalType = type; if (!type.deco) { sc = sc.push(); - sc.stc |= storage_class & STC.STCref; // forward refness to function type + sc.stc |= storage_class & STCref; // forward to function type type = type.semantic(loc, sc); sc = sc.pop(); @@ -387,13 +403,7 @@ size_t nparams = Parameter.dim(f.parameters); linkage = sc.linkage; - // if (!parent) - { - //parent = sc.scopesym; - parent = sc.parent; - } protection = sc.protection; - Dsymbol parent = toParent(); if (storage_class & STC.STCscope) error("functions cannot be scope"); @@ -434,7 +444,7 @@ { if (isCtorDeclaration()) { - return; + goto Ldone; } static if (false) { // Verify no constructors, destructors, etc. @@ -475,7 +485,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()); } @@ -545,8 +555,10 @@ 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: @@ -586,12 +598,14 @@ break; case -2: // can't determine because of fwd refs - cd.sizeok = 2; // can't finish due to forward reference - return; + cd.sizeok = 2; // can't finish due to forward reference + global.dprogress = dprogress_save; + return; default: { - FuncDeclaration fdv = cast(FuncDeclaration)cd.vtbl.data[vi]; + FuncDeclaration fdv = cast(FuncDeclaration)cd.baseClass.vtbl.data[vi]; + // This function is covariant with fdv if (fdv.isFinal()) error("cannot override final function %s", fdv.toPrettyChars()); @@ -665,6 +679,7 @@ case -2: cd.sizeok = 2; // can't finish due to forward reference + global.dprogress = dprogress_save; return; default: @@ -679,23 +694,25 @@ ti = fdv.tintro; else if (!type.equals(fdv.type)) { - /* Only need to have a tintro if the vptr - * offsets differ - */ - int offset; - if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset)) - { - ti = fdv.type; -static if (false) { - if (offset) - ti = fdv.type; - else if (type.nextOf().ty == Tclass) + /* Only need to have a tintro if the vptr + * offsets differ + */ + uint errors = global.errors; + global.gag++; // suppress printing of error messages + int offset; + int baseOf = fdv.type.nextOf().isBaseOf(type.nextOf(), &offset); + global.gag--; // suppress printing of error messages + if (errors != global.errors) { - ClassDeclaration cdn = (cast(TypeClass)type.nextOf()).sym; - if (cdn && cdn.sizeok != 1) - ti = fdv.type; - } -} + // 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 + global.dprogress = dprogress_save; + return; + } + if (baseOf) + { + ti = fdv.type; } } if (ti) @@ -717,6 +734,27 @@ } L2: ; + /* Go through all the interface bases. + * Disallow overriding any final functions in the interface(s). + */ + for (int i = 0; i < cd.interfaces_dim; i++) + { + BaseClass b = cd.interfaces[i]; + if (b.base) + { + Dsymbol s = search_function(b.base, ident); + if (s) + { + FuncDeclaration f_ = s.isFuncDeclaration(); + if (f_) + { + f_ = f_.overloadExactMatch(type); + if (f_ && f_.isFinal() && f_.prot() != PROT.PROTprivate) + error("cannot override final function %s.%s", b.base.toChars(), f_.toPrettyChars()); + } + } + } + } } else if (isOverride() && !parent.isTemplateInstance()) error("override only applies to class member functions"); @@ -807,7 +845,7 @@ } } - if (isVirtual()) + if (isVirtual() && semanticRun != PASSsemanticdone) { /* Rewrite contracts as nested functions, then call them. * Doing it as nested functions means that overriding functions @@ -863,6 +901,9 @@ } Ldone: + global.dprogress++; + semanticRun = PASSsemanticdone; + /* Save scope for possible later use (if we need the * function internals) */ @@ -904,9 +945,9 @@ //printf("\tlinkage = %d\n", sc.linkage); //printf(" sc.incontract = %d\n", sc.incontract); - if (semanticRun >= 3) - return; - semanticRun = 3; + if (semanticRun >= PASSsemantic3) + return; + semanticRun = PASSsemantic3; if (!type || type.ty != TY.Tfunction) return; @@ -1671,7 +1712,8 @@ sc2.callSuper = 0; sc2.pop(); } - semanticRun = 4; + + semanticRun = PASSsemantic3done; } // called from semantic3 @@ -1763,17 +1805,22 @@ /************************************************* * 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 */ int findVtblIndex(Array vtbl, int dim) { + FuncDeclaration mismatch = null; + int bestvi = -1; for (int vi = 0; vi < dim; vi++) { FuncDeclaration fdv = (cast(Dsymbol)vtbl.data[vi]).isFuncDeclaration(); if (fdv && fdv.ident is 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) @@ -1782,15 +1829,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 @@ -1801,7 +1845,15 @@ } } } - return -1; + if (bestvi == -1 && mismatch) + { + //type.print(); + //mismatch.type.print(); + //writef("%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; } /**************************************************** @@ -2328,7 +2380,11 @@ printf("result is %d\n", isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration()); } - return isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration(); + Dsymbol p = toParent(); + return isMember() && + !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && + p.isClassDeclaration() && + !(p.isInterfaceDeclaration() && isFinal()); } override bool isFinal() @@ -2404,7 +2460,7 @@ } } - if (cantInterpret || semanticRun == 3) + if (cantInterpret || semanticRun == PASSsemantic3) return null; if (!fbody) @@ -2413,13 +2469,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(); @@ -2433,21 +2489,6 @@ return null; } - // Ensure there are no lazy parameters - if (tf.parameters) - { - size_t dim = Parameter.dim(tf.parameters); - for (size_t i = 0; i < dim; i++) - { - auto arg = Parameter.getNth(tf.parameters, i); - if (arg.storageClass & STClazy) - { - cantInterpret = 1; - return null; - } - } - } - scope InterState istatex = new InterState(); istatex.caller = istate; istatex.fd = this; @@ -2479,7 +2520,7 @@ Expression earg = arguments[i]; auto arg = Parameter.getNth(tf.parameters, i); - if (arg.storageClass & (STCout | STCref)) + if (arg.storageClass & (STCout | STCref | STClazy)) { } else @@ -2686,7 +2727,7 @@ if (needThis() && !hasthis) return 0; - if (inlineNest || (semanticRun < 3 && !hdrscan)) + if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan)) { version (CANINLINE_LOG) { printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun); @@ -3292,10 +3333,9 @@ return; } - if (semanticRun >= 5) // if toObjFile() already run + if (semanticRun >= PASSobj) // if toObjFile() already run return; - - semanticRun = 5; + semanticRun = PASSobj; if (!func.fbody) { @@ -3349,18 +3389,25 @@ // Pull in RTL startup code if (func.isMain()) - { objextdef("_main"); + { + objextdef("_main"); version (POSIX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS obj_ehsections(); // initialize exception handling sections -} else { +} +version (TARGET_WINDOS) { objextdef("__acrtused_con"); } obj_includelib(libname); s.Sclass = SC.SCglobal; } else if (strcmp(s.Sident.ptr, "main".ptr) == 0 && linkage == LINK.LINKc) - s.Sclass = SC.SCglobal; - + { +version (TARGET_WINDOS) { + objextdef("__acrtused_con"); // bring in C startup code + obj_includelib("snn.lib"); // bring in C runtime library +} + s.Sclass = SCglobal; + } else if (func.isWinMain()) { objextdef("__acrtused"); @@ -3640,32 +3687,54 @@ } // If static constructor - if (isStaticConstructor()) + if (isSharedStaticCtorDeclaration()) // must come first because it derives from StaticCtorDeclaration { - elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s)); + elem* e = el_una(OPucall, TYvoid, el_var(s)); + global.esharedctor = el_combine(global.esharedctor, e); + } + else if (isStaticCtorDeclaration()) + { + elem* e = el_una(OPucall, TYvoid, el_var(s)); global.ector = el_combine(global.ector, e); } // If static destructor - if (isStaticDestructor()) + if (auto f_ = isSharedStaticDtorDeclaration()) // must come first because it derives from StaticDtorDeclaration { elem* e; version (STATICCTOR) { - e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_FATEXIT]), el_ptr(s)); - ector = el_combine(ector, e); + e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s)); + esharedctor = el_combine(esharedctor, e); + shareddtorcount++; +} else { + if (f_.vgate) + { + /* Increment destructor's vgate at construction time + */ + global.esharedctorgates.push(cast(void*)f_); + } + + e = el_una(OPucall, TYvoid, el_var(s)); + global.eshareddtor = el_combine(e, global.eshareddtor); +} + } + else if (auto f_ = isStaticDtorDeclaration()) + { + elem* e; + +version (STATICCTOR) { + e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s)); + global.ector = el_combine(ector, e); dtorcount++; } else { - StaticDtorDeclaration f2 = isStaticDtorDeclaration(); - assert(f2); - if (f2.vgate) - { - /* Increment destructor's vgate at construction time + if (f_.vgate) + { /* Increment destructor's vgate at construction time */ - global.ectorgates.push(cast(void*)f2); + global.ectorgates.push(cast(void*)f_); } - e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s)); + e = el_una(OPucall, TYvoid, el_var(s)); global.edtor = el_combine(e, global.edtor); } }